Share Pastebin
Guest
Public paste!

TiZ

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