Guest
Public paste!

TiZ

By: a guest | Mar 21st, 2010 | Syntax: None | Size: 11.98 KB | Hits: 35 | Expires: Never
This paste has a previous version, view the difference. Copy text to clipboard
  1. // Copyright (c) 2010 Trent McPheron <twilightinzero@gmail.com>
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20.  
  21. using Xfce;
  22. using Gtk;
  23. using Pango;
  24. using Wnck;
  25.  
  26. ///////////////////
  27. // Namebar
  28. ///////////////////
  29.  
  30. public class NamebarPlugin : GLib.Object
  31. {
  32.         ///////////////////
  33.         // Init stuff
  34.         ///////////////////
  35.        
  36.         static NamebarPlugin namebar;
  37.        
  38.         public static void register (Xfce.PanelPlugin plugin)
  39.         {
  40.         namebar = new NamebarPlugin (plugin);
  41.         plugin.size_changed.connect((p, s) => {
  42.             plugin.set_size_request(namebar.size, -1);
  43.         });
  44.     }
  45.  
  46.     public static int main (string[] args)
  47.     {
  48.         return Xfce.PanelPluginRegisterExternal(ref args, register);
  49.     }  
  50.        
  51.        
  52.         ///////////////////
  53.         // Properties
  54.         ///////////////////
  55.        
  56.         public bool   only_max      { get; set; default = true; }
  57.         public int16  size          { get; set; default = 240; }
  58.         public bool   expand        { get; set; default = true; }
  59.         public bool   active_bold   { get; set; default = true; }
  60.         public bool   passive_bold  { get; set; default = true; }
  61.         public Color  active_color  { get; set; default = Color(); }
  62.         public Color  passive_color { get; set; default = Color(); }
  63.        
  64.        
  65.         ///////////////////
  66.         // Fields
  67.         ///////////////////
  68.        
  69.         // Xfce4 Panel Plugin.
  70.         private weak PanelPlugin plugin;
  71.        
  72.         // Wnck stuff.
  73.         private unowned Screen screen;
  74.         private unowned Wnck.Window window;
  75.        
  76.         // Gtk widgets.
  77.         private HBox box;
  78.         private Image window_icon;
  79.         private Image minimize_icon;
  80.         private Image max_res_icon;
  81.         private Image close_icon;
  82.         private Label title_label;
  83.        
  84.         // Theme stuff.
  85.         private List<File> theme_list;
  86.         private Theme theme;
  87.        
  88.        
  89.         ///////////////////
  90.         // Constructor
  91.         ///////////////////
  92.        
  93.         // The real constructor.
  94.         public NamebarPlugin (PanelPlugin plugin)
  95.         {
  96.                 // Panel plugin.
  97.                 this.plugin = plugin;
  98.                
  99.                 // Default colors.
  100.                 active_color.parse("#ECECEC");
  101.                 passive_color.parse("#888888");
  102.                
  103.                 // Default theme.
  104.                 File tf = File.new_for_path("~/.config/namebar/themes/New Wave-ish");
  105.                 theme = Theme(tf);
  106.                
  107.                 // Get wnck ready.
  108.                 set_client_type(ClientType.PAGER);
  109.                 screen = Screen.get_default();
  110.                
  111.                 // Wnck.Window icon.
  112.                 EventBox eb1 = new EventBox();
  113.                 eb1.visible_window = false;
  114.                 window_icon = new Image();
  115.                 eb1.add(window_icon);
  116.                
  117.                 // Title label.
  118.                 EventBox eb2 = new EventBox();
  119.                 eb2.visible_window = false;
  120.                 title_label = new Label();
  121.                 title_label.set_alignment(0.0, 0.5);
  122.                 title_label.ellipsize = EllipsizeMode.END;
  123.                 eb2.add(title_label);
  124.                
  125.                 // Minimize button.
  126.                 EventBox eb3 = new EventBox();
  127.                 eb3.visible_window = false;
  128.                 minimize_icon = new Image();
  129.                 eb3.add(minimize_icon);
  130.                
  131.                 // Maximize/Restore button.
  132.                 EventBox eb4 = new EventBox();
  133.                 eb4.visible_window = false;
  134.                 max_res_icon = new Image();
  135.                 eb4.add(max_res_icon);
  136.                
  137.                 // Close button.
  138.                 EventBox eb5 = new EventBox();
  139.                 eb5.visible_window = false;
  140.                 close_icon = new Image();
  141.                 eb5.add(close_icon);
  142.                
  143.                 // Create container box.
  144.                 box = new HBox();
  145.                 box.spacing = 0;
  146.                 box.pack_start(eb1, false, false, 0);
  147.                 box.pack_start(eb2, true, true, 2);
  148.                 box.pack_start(eb3, false, false, 0);
  149.                 box.pack_start(eb4, false, false, 0);
  150.                 box.pack_start(eb5, false, false, 0);
  151.                 plugin.add(box);
  152.                 plugin.set_expand(true);
  153.                
  154.                 // Connect signals.
  155.                 screen.active_window_changed.connect(find_window);
  156.                 screen.window_closed.connect(find_window);
  157.                 eb2.button_press_event.connect((w, e) => { window.activate(e.time); });
  158.                 eb3.enter_notify_event.connect(button_entered);
  159.                 eb3.leave_notify_event.connect(button_left);
  160.                 eb3.button_press_event.connect(button_pressed);
  161.                 eb3.button_release_event.connect(button_released);
  162.                 eb4.enter_notify_event.connect(button_entered);
  163.                 eb4.leave_notify_event.connect(button_left);
  164.                 eb4.button_press_event.connect(button_pressed);
  165.                 eb4.button_release_event.connect(button_released);
  166.                 eb5.enter_notify_event.connect(button_entered);
  167.                 eb5.leave_notify_event.connect(button_left);
  168.                 eb5.button_press_event.connect(button_pressed);
  169.                 eb5.button_release_event.connect(button_released);
  170.                
  171.                 // Find a window to show.
  172.                 find_window();
  173.         }
  174.        
  175.        
  176.         ///////////////////
  177.         // Functions
  178.         ///////////////////
  179.        
  180.         // Find a list of themes.
  181.         private List<Theme> find_themes ()
  182.         {
  183.                 List<Theme> list = new List<Theme>();
  184.                 File usr_dir = File.new_for_path("/usr/share/namebar/themes");
  185.                 File home_dir = File.new_for_path("~/.config/namebar/themes");
  186.                 File[] dirs = { usr_dir, home_dir };
  187.                
  188.                 // Check each directory to see if it exists.
  189.                 for (uint8 i = 0; i < 2; i++)
  190.                 if (dirs[i].query_exists())
  191.                 {
  192.                         // Get an enumerator for the directory.
  193.                         FileEnumerator enumerator =
  194.                                 usr_dir.enumerate_children(
  195.                                         FILE_ATTRIBUTE_STANDARD_NAME, 0, null);
  196.                                        
  197.                         // Iterate through all the children and try to
  198.                         // load the themes in each. If successful, add
  199.                         // them to the theme list.
  200.                         FileInfo next_file;
  201.                         while ((next_file = enumerator.next_file(null)) != null)
  202.                         {
  203.                                 File theme_file = File.get_child(next_file.get_name());
  204.                                 Theme theme = Theme(theme_file);
  205.                                 if (theme.valid)
  206.                                         list.append(theme);
  207.                         }
  208.                 }
  209.                
  210.                 // If the theme list is empty, let the user know.
  211.                 if (list.length() == 0)
  212.                         stdout.printf("There are no valid themes.");
  213.                        
  214.                 // Return the list.
  215.                 return list;
  216.         }
  217.        
  218.         // Refreshes the theme details and label attributes.
  219.         private void refresh_theme ()
  220.         {
  221.                 set_button_state(minimize_icon, ButtonState.NORMAL);
  222.                 set_button_state(max_res_icon, ButtonState.NORMAL);
  223.                 set_button_state(close_icon, ButtonState.NORMAL);
  224.                 bool active = window.is_active();
  225.                 bool bold = (active ? active_bold : passive_bold);
  226.                 AttrList al = new AttrList();
  227.                 AttrColor ac = new AttrColor();
  228.                 ac.color = (active ? active_color : passive_color);
  229.                 Attribute aw = attr_weight_new(Weight.BOLD);
  230.                 title_label.attributes.change(ac);
  231.                 title_label.attributes.change(aw);
  232.         }
  233.        
  234.         // Changes the currently shown window.
  235.         private void set_current_window (Wnck.Window new_win)
  236.         {
  237.                 // We don't need the old window firing events.
  238.                 if (window != null)
  239.                 {
  240.                         window.name_changed.disconnect(window_name_changed);
  241.                         window.icon_changed.disconnect(window_icon_changed);
  242.                         window.state_changed.disconnect(find_window);
  243.                 }
  244.                
  245.                 // Set the window.
  246.                 window = new_win;
  247.                
  248.                 // Connect the new events.
  249.                 window.name_changed.connect(window_name_changed);
  250.                 window.icon_changed.connect(window_icon_changed);
  251.                 window.state_changed.connect(find_window);
  252.                
  253.                 // Reset attributes.
  254.                 window_name_changed();
  255.                 window_icon_changed();
  256.                 refresh_theme();
  257.                
  258.                 // Show everything in the box.
  259.                 box.show_all();
  260.         }
  261.        
  262.         // Hides the namebar if there is no valid window.
  263.         private void set_none ()
  264.         {
  265.                 // Disconnect the old window's events.
  266.                 if (window != null)
  267.                 {
  268.                         window.name_changed.disconnect(window_name_changed);
  269.                         window.icon_changed.disconnect(window_icon_changed);
  270.                         window.state_changed.disconnect(find_window);
  271.                 }
  272.                
  273.                 // Set window to null.
  274.                 window = null;
  275.                
  276.                 // Hide everything in the box.
  277.                 box.hide_all();
  278.         }
  279.        
  280.         // Finds a window to show.
  281.         private void find_window ()
  282.         {
  283.                 // Get the active window.
  284.                 unowned Wnck.Window active_window = screen.get_active_window();
  285.                
  286.                 // If we're not only using max'd windows, check the
  287.                 // active window and set the window if it fits.
  288.                 if (!only_max && !active_window.is_skip_tasklist() &&
  289.                     (active_window.get_window_type() == Wnck.WindowType.NORMAL ||
  290.                      active_window.get_window_type() == Wnck.WindowType.DIALOG))
  291.                 {
  292.                         set_window(active_window);
  293.                         return;
  294.                 }
  295.                        
  296.                 // If we're using the topmost maximized window...
  297.                 if (only_max)
  298.                 {
  299.                         // Get the list of stacked windows.
  300.                         List<Wnck.Window> window_stack = screen.get_windows_stacked();
  301.                        
  302.                         // Iterate through in reverse.
  303.                         for (uint16 i = window_stack.length() - 1; i >= 0; i--)
  304.                         {
  305.                                 // Check the window, and if it fits, set it.
  306.                                 Wnck.Window w = window_stack.nth_data(i);
  307.                                 if (w.is_maximized() &&
  308.                                     !w.is_minimized() &&
  309.                                     !w.is_skip_tasklist() &&
  310.                                     (w.get_window_type() == Wnck.WindowType.NORMAL ||
  311.                                      w.get_window_type() == Wnck.WindowType.DIALOG))
  312.                                 {
  313.                                         set_window(w);
  314.                                         return;
  315.                                 }
  316.                         }
  317.                 }
  318.                
  319.                 // If we still don't have a window,
  320.                 // set it to none.
  321.                 set_none();
  322.         }
  323.        
  324.         // Sets the state of a button.
  325.         private void set_button_state (Image img, ButtonState bs)
  326.         {
  327.                 // Get stuff ready.
  328.                 bool active = window.is_active();
  329.                 ThemeButton tb;
  330.                
  331.                 // Determine which button we're on.
  332.                 if (img == minimize_icon) tb = ThemeButton.MINIMIZE;
  333.                 else if (img == close_icon) tb = ThemeButton.CLOSE;
  334.                 else
  335.                 {
  336.                         if (window.is_maximized()) tb = ThemeButton.MAXIMIZE;
  337.                         else tb = ThemeButton.RESTORE;
  338.                 }
  339.                
  340.                 // Set the pixbuf on the image.
  341.                 img.pixbuf = theme.get_pixbuf(active, tb, bs);
  342.         }
  343.        
  344.        
  345.         ///////////////////
  346.         // Events
  347.         ///////////////////
  348.        
  349.         // Emitted when the window's name changes.
  350.         private void window_name_changed ()
  351.         {
  352.                 string name = window.get_name();
  353.                 title_label.label = name;
  354.                 title_label.tooltip_text = name;
  355.         }
  356.        
  357.         // Emitted when the window's icon changes.
  358.         // I don't know anything about disconnecting lambda
  359.         // expressions, so this one-line method's here.
  360.         private void window_icon_changed ()
  361.         {
  362.                 window_icon.pixbuf = window.get_mini_icon();
  363.         }
  364.        
  365.         // Changes the icon once a button is entered.
  366.         private void button_entered (Widget sender)
  367.         {
  368.                 Image img = (sender as EventBox).child as Image;
  369.                 set_button_state(img, ButtonState.HOVER);
  370.         }
  371.        
  372.         // Changes the icon once a button is left.
  373.         private void button_left (Widget sender)
  374.         {
  375.                 Image img = (sender as EventBox).child as Image;
  376.                 set_button_state(img, ButtonState.NORMAL);
  377.         }
  378.        
  379.         // Changes the icon once a button is pressed.
  380.         private void button_pressed (Widget sender, Gdk.EventButton event)
  381.         {
  382.                 if (event.button == 1)
  383.                 {
  384.                         Image img = (sender as EventBox).child as Image;
  385.                         set_button_state(img, ButtonState.HOVER);
  386.                 }
  387.         }
  388.        
  389.         // Performs an action when an button is released.
  390.         private void button_released (Widget sender, Gdk.EventButton event)
  391.         {
  392.                 // Preparation for below check.
  393.                 int x, y;
  394.                 sender.get_pointer(out x, out y);
  395.                 Allocation a = sender.allocation;
  396.                
  397.                 // Abort method if the main button wasn't released
  398.                 // inside the event box.
  399.                 if (x < 0 || y < 0 ||
  400.                     x > a.width || y > a.height ||
  401.                     event.button != 1) return;
  402.                
  403.                 // Determine what to do based on which icon was
  404.                 // clicked and do it.
  405.                 Image img = (sender as EventBox).child as Image;
  406.                 if (img = minimize_icon) window.minimize();
  407.                 else if (img = close_icon) window.close(event.time);
  408.                 else if (img = max_res_icon)
  409.                 {
  410.                         if (window.is_maximized()) window.unmaximize();
  411.                         else window.maximize();
  412.                 }
  413.                
  414.                 // Set the button state to normal.
  415.                 set_button_state(img, ButtonState.NORMAL);
  416.         }
  417. }
  418.  
  419.  
  420. ///////////////////
  421. // XFCE Module
  422. ///////////////////
  423.  
  424. [ModuleInit]
  425. public Type xfce_panel_module_init (TypeModule module) {
  426.         return typeof(NamebarPlugin);
  427. }