[Xfce4-commits] <xfce4-terminal:nick/dropdown> Initial import of the --drop-down functionality.

Nick Schermer noreply at xfce.org
Fri Dec 28 23:12:03 CET 2012


Updating branch refs/heads/nick/dropdown
         to 2076c677fffce40c51c7f226fcde690a2ccad2c1 (commit)
       from 7ac4ebaf1f564388e0cc4a46c5d59ed47019cb7e (commit)

commit 2076c677fffce40c51c7f226fcde690a2ccad2c1
Author: Nick Schermer <nick at xfce.org>
Date:   Fri Dec 28 23:11:29 2012 +0100

    Initial import of the --drop-down functionality.

 terminal/Makefile.am                |   10 +-
 terminal/terminal-app.c             |  128 +++++++++----
 terminal/terminal-dialogs.c         |   56 ++++++
 terminal/terminal-dialogs.h         |    5 +
 terminal/terminal-options.c         |    4 +
 terminal/terminal-options.h         |    1 +
 terminal/terminal-screen.c          |  148 +++++++++-------
 terminal/terminal-screen.h          |    6 +
 terminal/terminal-search-dialog.c   |   12 ++-
 terminal/terminal-window-dropdown.c |  338 +++++++++++++++++++++++++++++++++++
 terminal/terminal-window-dropdown.h |   46 +++++
 terminal/terminal-window.c          |  134 ++++++---------
 terminal/terminal-window.h          |   51 ++++++
 13 files changed, 749 insertions(+), 190 deletions(-)

diff --git a/terminal/Makefile.am b/terminal/Makefile.am
index cb1b96f..8cb9e2f 100644
--- a/terminal/Makefile.am
+++ b/terminal/Makefile.am
@@ -28,7 +28,8 @@ xfce4_terminal_headers = \
 	terminal-private.h \
 	terminal-screen.h \
 	terminal-widget.h \
-	terminal-window.h \
+	terminal-window.h \ \
+	terminal-window-dropdown.h \
 	terminal-window-ui.h
 
 xfce4_terminal_SOURCES = \
@@ -46,24 +47,25 @@ xfce4_terminal_SOURCES = \
 	terminal-search-dialog.c \
 	terminal-screen.c \
 	terminal-widget.c \
-	terminal-window.c
+	terminal-window.c \
+	terminal-window-dropdown.c
 
 xfce4_terminal_CFLAGS = \
 	$(GTK_CFLAGS) \
 	$(GIO_CFLAGS) \
-	$(LIBX11_CFLAGS)\
+	$(LIBX11_CFLAGS) \
 	$(VTE_CFLAGS) \
 	$(LIBXFCE4UI_CFLAGS) \
 	$(PLATFORM_CFLAGS)
 
 xfce4_terminal_LDFLAGS = \
 	-no-undefined \
+	$(LIBX11_LDFLAGS) \
 	$(PLATFORM_LDFLAGS)
 
 xfce4_terminal_LDADD = \
 	$(GTK_LIBS) \
 	$(GIO_LIBS) \
-	$(LIBX11_LDFLAGS) \
 	$(LIBX11_LIBS) \
 	$(VTE_LIBS) \
 	$(LIBXFCE4UI_LIBS) \
diff --git a/terminal/terminal-app.c b/terminal/terminal-app.c
index 7b4334f..6ecf0ec 100644
--- a/terminal/terminal-app.c
+++ b/terminal/terminal-app.c
@@ -43,6 +43,7 @@
 #include <terminal/terminal-preferences.h>
 #include <terminal/terminal-private.h>
 #include <terminal/terminal-window.h>
+#include <terminal/terminal-window-dropdown.h>
 
 #define ACCEL_MAP_PATH "xfce4/terminal/accels.scm"
 
@@ -53,12 +54,6 @@ static void               terminal_app_update_accels            (TerminalApp
 static void               terminal_app_update_mnemonics         (TerminalApp        *app);
 static gboolean           terminal_app_accel_map_load           (gpointer            user_data);
 static gboolean           terminal_app_accel_map_save           (gpointer            user_data);
-static GtkWidget         *terminal_app_create_window            (TerminalApp        *app,
-                                                                 const gchar        *role,
-                                                                 gboolean            fullscreen,
-                                                                 TerminalVisibility  menubar,
-                                                                 TerminalVisibility  borders,
-                                                                 TerminalVisibility  toolbar);
 static void               terminal_app_new_window               (TerminalWindow     *window,
                                                                  const gchar        *working_directory,
                                                                  TerminalApp        *app);
@@ -293,6 +288,29 @@ terminal_app_accel_map_load (gpointer user_data)
 
 
 
+static void
+terminal_app_take_window (TerminalApp *app,
+                          GtkWindow   *window)
+{
+  GtkWindowGroup *group;
+
+  terminal_return_if_fail (GTK_IS_WINDOW (window));
+
+  group = gtk_window_group_new ();
+  gtk_window_group_add_window (group, window);
+  g_object_weak_ref (G_OBJECT (window), (GWeakNotify) g_object_unref, group);
+
+  g_signal_connect (G_OBJECT (window), "destroy",
+                    G_CALLBACK (terminal_app_window_destroyed), app);
+  g_signal_connect (G_OBJECT (window), "new-window",
+                    G_CALLBACK (terminal_app_new_window), app);
+  g_signal_connect (G_OBJECT (window), "new-window-with-screen",
+                    G_CALLBACK (terminal_app_new_window_with_terminal), app);
+  app->windows = g_slist_prepend (app->windows, window);
+}
+
+
+
 static GtkWidget*
 terminal_app_create_window (TerminalApp       *app,
                             const gchar       *role,
@@ -303,7 +321,6 @@ terminal_app_create_window (TerminalApp       *app,
 {
   GtkWidget *window;
   gchar     *new_role = NULL;
-  GtkWindowGroup *group;
 
   if (role == NULL)
     {
@@ -313,20 +330,23 @@ terminal_app_create_window (TerminalApp       *app,
     }
 
   window = terminal_window_new (role, fullscreen, menubar, borders, toolbar);
+  g_free (new_role);
 
-  group = gtk_window_group_new ();
-  gtk_window_group_add_window (group, GTK_WINDOW (window));
-  g_object_weak_ref (G_OBJECT (window), (GWeakNotify) g_object_unref, group);
+  terminal_app_take_window (app, GTK_WINDOW (window));
 
-  g_signal_connect (G_OBJECT (window), "destroy",
-                    G_CALLBACK (terminal_app_window_destroyed), app);
-  g_signal_connect (G_OBJECT (window), "new-window",
-                    G_CALLBACK (terminal_app_new_window), app);
-  g_signal_connect (G_OBJECT (window), "new-window-with-screen",
-                    G_CALLBACK (terminal_app_new_window_with_terminal), app);
-  app->windows = g_slist_prepend (app->windows, window);
+  return window;
+}
 
-  g_free (new_role);
+
+
+static GtkWidget*
+terminal_app_create_drop_down (TerminalApp *app)
+{
+  GtkWidget *window;
+
+  window = terminal_window_dropdown_new ();
+
+  terminal_app_take_window (app, GTK_WINDOW (window));
 
   return window;
 }
@@ -441,9 +461,13 @@ terminal_app_save_yourself (XfceSMClient *client,
   gint                  argc;
   gint                  n;
 
-  for (lp = app->windows; lp != NULL; lp = lp->next)
+  for (lp = app->windows, n = 0; lp != NULL; lp = lp->next)
     {
-      if (lp != app->windows)
+      /* don't session save dropdown windows */
+      if (TERMINAL_IS_WINDOW_DROPDOWN (lp->data))
+        continue;
+
+      if (n++ != 0)
         result = g_slist_append (result, g_strdup ("--window"));
       result = g_slist_concat (result, terminal_window_get_restart_command (lp->data));
     }
@@ -557,8 +581,25 @@ terminal_app_open_window (TerminalApp        *app,
   terminal_return_if_fail (TERMINAL_IS_APP (app));
   terminal_return_if_fail (attr != NULL);
 
-  if (attr->reuse_last_window
-      && app->windows != NULL)
+  if (attr->drop_down)
+    {
+      /* look for an exising drop-down window */
+      for (lp = app->windows; lp != NULL; lp = lp->next)
+        if (TERMINAL_IS_WINDOW_DROPDOWN (lp->data))
+          break;
+
+      if (lp != NULL)
+        {
+          /* toggle state of visible window */
+          terminal_window_dropdown_toggle (lp->data, attr->startup_id);
+          return;
+        }
+
+      /* create new drop-down window */
+      window = terminal_app_create_drop_down (app);
+    }
+  else if (attr->reuse_last_window
+           && app->windows != NULL)
     {
       /* open the tabs in an existing window */
       window = app->windows->data;
@@ -574,11 +615,13 @@ terminal_app_open_window (TerminalApp        *app,
                                            attr->borders,
                                            attr->toolbar);
 
-      if (attr->startup_id != NULL)
-        gtk_window_set_startup_id (GTK_WINDOW (window), attr->startup_id);
+      /* apply normal window properties */
       if (attr->maximize)
         gtk_window_maximize (GTK_WINDOW (window));
 
+      if (attr->startup_id != NULL)
+        gtk_window_set_startup_id (GTK_WINDOW (window), attr->startup_id);
+
       if (attr->icon != NULL)
         {
           if (g_path_is_absolute (attr->icon))
@@ -595,6 +638,7 @@ terminal_app_open_window (TerminalApp        *app,
         }
     }
 
+  /* add the tabs */
   for (lp = attr->tabs; lp != NULL; lp = lp->next)
     {
       terminal = g_object_new (TERMINAL_TYPE_SCREEN, NULL);
@@ -617,23 +661,29 @@ terminal_app_open_window (TerminalApp        *app,
   if (reuse_window)
     return;
 
-  /* set the window geometry, this can only be set after one of the tabs
-   * has been added, because vte is the geometry widget, so atleast one
-   * call should have been made to terminal_screen_set_window_geometry_hints */
-  if (G_LIKELY (attr->geometry == NULL))
-    g_object_get (G_OBJECT (app->preferences), "misc-default-geometry", &geometry, NULL);
-  else
-    geometry = g_strdup (attr->geometry);
+  if (!attr->drop_down)
+    {
+      /* set the window geometry, this can only be set after one of the tabs
+       * has been added, because vte is the geometry widget, so atleast one
+       * call should have been made to terminal_screen_set_window_geometry_hints */
+      if (G_LIKELY (attr->geometry == NULL))
+        g_object_get (G_OBJECT (app->preferences), "misc-default-geometry", &geometry, NULL);
+      else
+        geometry = g_strdup (attr->geometry);
 
-  /* try to apply the geometry to the window */
-  if (!gtk_window_parse_geometry (GTK_WINDOW (window), geometry))
-    g_printerr (_("Invalid geometry string \"%s\"\n"), geometry);
+      /* try to apply the geometry to the window */
+      if (!gtk_window_parse_geometry (GTK_WINDOW (window), geometry))
+        g_printerr (_("Invalid geometry string \"%s\"\n"), geometry);
 
-  /* cleanup */
-  g_free (geometry);
+      /* cleanup */
+      g_free (geometry);
+    }
 
   /* show the window */
-  gtk_widget_show (window);
+  if (attr->drop_down)
+    terminal_window_dropdown_toggle (TERMINAL_WINDOW_DROPDOWN (window), attr->startup_id);
+  else
+    gtk_widget_show (window);
 }
 
 
diff --git a/terminal/terminal-dialogs.c b/terminal/terminal-dialogs.c
index bb109e5..04ecc8b 100644
--- a/terminal/terminal-dialogs.c
+++ b/terminal/terminal-dialogs.c
@@ -29,6 +29,12 @@
 
 #include <libxfce4util/libxfce4util.h>
 
+#include <gdk/gdk.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+#endif
+
 #include <terminal/terminal-dialogs.h>
 #include <terminal/terminal-private.h>
 
@@ -84,3 +90,53 @@ terminal_dialogs_show_about (GtkWindow *parent)
                          "website-label", _("Visit Terminal website"),
                          NULL);
 }
+
+
+
+void
+terminal_set_style_thinkess (GtkWidget *widget,
+                             gint       thinkness)
+{
+  GtkRcStyle *style;
+
+  style = gtk_rc_style_new ();
+  style->xthickness = style->ythickness = thinkness;
+  gtk_widget_modify_style (widget, style);
+  g_object_unref (G_OBJECT (style));
+}
+
+
+
+void
+terminal_activate_window (GtkWindow *window)
+{
+#ifdef GDK_WINDOWING_X11
+  XClientMessageEvent event;
+
+  terminal_return_if_fail (GTK_IS_WINDOW (window));
+  terminal_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (window)));
+
+  /* we need a slightly custom version of the call through Gtk+ to
+   * properly focus the panel when a plugin calls
+   * xfce_panel_plugin_focus_widget() */
+  event.type = ClientMessage;
+  event.window = GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (window)));
+  event.message_type = gdk_x11_get_xatom_by_name ("_NET_ACTIVE_WINDOW");
+  event.format = 32;
+  event.data.l[0] = 0;
+
+  gdk_error_trap_push ();
+
+  XSendEvent (gdk_x11_get_default_xdisplay (),
+              gdk_x11_get_default_root_xwindow (), False,
+              StructureNotifyMask, (XEvent *) &event);
+
+  gdk_flush ();
+
+  if (gdk_error_trap_pop () != 0)
+    g_critical ("Failed to focus window");
+#else
+  /* our best guess on non-x11 clients */
+  gtk_window_present (window);
+#endif
+}
diff --git a/terminal/terminal-dialogs.h b/terminal/terminal-dialogs.h
index e58f7df..1efbb30 100644
--- a/terminal/terminal-dialogs.h
+++ b/terminal/terminal-dialogs.h
@@ -25,6 +25,11 @@ G_BEGIN_DECLS
 
 void terminal_dialogs_show_about (GtkWindow    *parent);
 
+void terminal_set_style_thinkess (GtkWidget    *widget,
+                                  gint          thinkness);
+
+void terminal_activate_window    (GtkWindow    *window);
+
 G_END_DECLS
 
 #endif /* !__TERMINAL_DIALOGS_H__ */
diff --git a/terminal/terminal-options.c b/terminal/terminal-options.c
index 64e2f2e..c4ad677 100644
--- a/terminal/terminal-options.c
+++ b/terminal/terminal-options.c
@@ -394,6 +394,10 @@ terminal_window_attr_parse (gint              argc,
               win_attr->icon = g_strdup (s);
             }
         }
+      else if (terminal_option_cmp ("drop-down", 0, argc, argv, &n, NULL))
+        {
+          win_attr->drop_down = TRUE;
+        }
       else if (terminal_option_show_hide_cmp ("menubar", argc, argv, &n, &visible))
         {
           win_attr->menubar = visible;
diff --git a/terminal/terminal-options.h b/terminal/terminal-options.h
index 591d36b..15c6a01 100644
--- a/terminal/terminal-options.h
+++ b/terminal/terminal-options.h
@@ -47,6 +47,7 @@ struct _TerminalTabAttr
 struct _TerminalWindowAttr
 {
   GSList              *tabs;
+  guint                drop_down : 1;
   gchar               *display;
   gchar               *geometry;
   gchar               *role;
diff --git a/terminal/terminal-screen.c b/terminal/terminal-screen.c
index 98df97c..429cb5c 100644
--- a/terminal/terminal-screen.c
+++ b/terminal/terminal-screen.c
@@ -1237,34 +1237,27 @@ terminal_screen_vte_resize_window (VteTerminal    *terminal,
                                    TerminalScreen *screen)
 {
   GtkWidget *toplevel;
-  gint       xpad = 0;
-  gint       ypad = 0;
+  gint       xpad;
+  gint       ypad;
   glong      grid_width;
   glong      grid_height;
-  GtkBorder *border = NULL;
+  glong      char_width;
+  glong      char_height;
 
   terminal_return_if_fail (VTE_IS_TERMINAL (terminal));
   terminal_return_if_fail (TERMINAL_IS_SCREEN (screen));
 
   /* don't do anything if the window is already fullscreen/maximized */
   toplevel = gtk_widget_get_toplevel (GTK_WIDGET (screen));
-  if (!GTK_WIDGET_REALIZED (toplevel)
+  if (!gtk_widget_get_realized (toplevel)
       || (gdk_window_get_state (toplevel->window)
           & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) != 0)
     return;
 
-  /* we have to calculate the grid size, because the signal
-   * returns a size in pixels */
-  gtk_widget_style_get (GTK_WIDGET (terminal), "inner-border", &border, NULL);
-  if (border != NULL)
-    {
-      xpad = border->left + border->right;
-      ypad = border->top + border->bottom;
-      gtk_border_free (border);
-    }
+  terminal_screen_get_geometry (screen, &char_width, &char_height, &xpad, &ypad);
 
-  grid_width = (width - xpad) / terminal->char_width;
-  grid_height = (height - ypad) / terminal->char_height;
+  grid_width = (width - xpad) / char_width;
+  grid_height = (height - ypad) / char_height;
 
   /* leave if there is nothing to resize */
   if (terminal->column_count == grid_width
@@ -1274,8 +1267,10 @@ terminal_screen_vte_resize_window (VteTerminal    *terminal,
   /* set the terminal size and resize the window if it is active */
   vte_terminal_set_size (terminal, grid_width, grid_height);
   if (screen == terminal_window_get_active (TERMINAL_WINDOW (toplevel)))
-    terminal_screen_force_resize_window (screen, GTK_WINDOW (toplevel),
-                                         grid_width, grid_height);
+    {
+      terminal_screen_force_resize_window (screen, GTK_WINDOW (toplevel),
+                                           grid_width, grid_height);
+    }
 }
 
 
@@ -1649,6 +1644,46 @@ terminal_screen_set_size (TerminalScreen *screen,
 
 
 
+void
+terminal_screen_get_geometry (TerminalScreen *screen,
+                              glong          *char_width,
+                              glong          *char_height,
+                              gint           *xpad,
+                              gint           *ypad)
+{
+  GtkBorder *border = NULL;
+
+  terminal_return_if_fail (TERMINAL_IS_SCREEN (screen));
+  terminal_return_if_fail (VTE_IS_TERMINAL (screen->terminal));
+
+  if (char_width != NULL)
+    *char_width = vte_terminal_get_char_width (VTE_TERMINAL (screen->terminal));
+  if (char_height != NULL)
+    *char_height = vte_terminal_get_char_height (VTE_TERMINAL (screen->terminal));
+
+  if (xpad != NULL || ypad != NULL)
+    {
+      gtk_widget_style_get (GTK_WIDGET (screen->terminal), "inner-border", &border, NULL);
+      if (G_LIKELY (border != NULL))
+        {
+          if (xpad != NULL)
+            *xpad = border->left + border->right;
+          if (ypad != NULL)
+            *ypad = border->top + border->bottom;
+          gtk_border_free (border);
+        }
+      else
+        {
+          if (xpad != NULL)
+            *xpad = 0;
+          if (ypad != NULL)
+            *ypad = 0;
+        }
+    }
+}
+
+
+
 /**
  * terminal_screen_set_window_geometry_hints:
  *
@@ -1660,27 +1695,24 @@ terminal_screen_set_window_geometry_hints (TerminalScreen *screen,
                                            GtkWindow      *window)
 {
   GdkGeometry  hints;
-  gint         xpad = 0;
-  gint         ypad = 0;
-  GtkBorder   *border = NULL;
+  gint         xpad;
+  gint         ypad;
+  glong        char_width;
+  glong        char_height;
 
   terminal_return_if_fail (TERMINAL_IS_SCREEN (screen));
   terminal_return_if_fail (VTE_IS_TERMINAL (screen->terminal));
   terminal_return_if_fail (GTK_WIDGET_REALIZED (screen));
   terminal_return_if_fail (GTK_WIDGET_REALIZED (window));
 
-  gtk_widget_style_get (GTK_WIDGET (screen->terminal), "inner-border", &border, NULL);
-  if (border != NULL)
-    {
-      xpad = border->left + border->right;
-      ypad = border->top + border->bottom;
-      gtk_border_free (border);
-    }
+  terminal_screen_get_geometry (screen,
+                                &char_width, &char_height,
+                                &xpad, &ypad);
 
   hints.base_width = xpad;
   hints.base_height = ypad;
-  hints.width_inc = VTE_TERMINAL (screen->terminal)->char_width ;
-  hints.height_inc = VTE_TERMINAL (screen->terminal)->char_height;
+  hints.width_inc = char_width;
+  hints.height_inc = char_height;
   hints.min_width = hints.base_width + hints.width_inc * 4;
   hints.min_height = hints.base_height + hints.height_inc * 2;
 
@@ -1703,18 +1735,17 @@ terminal_screen_set_window_geometry_hints (TerminalScreen *screen,
 void
 terminal_screen_force_resize_window (TerminalScreen *screen,
                                      GtkWindow      *window,
-                                     glong           force_columns,
-                                     glong           force_rows)
+                                     glong           columns,
+                                     glong           rows)
 {
   GtkRequisition terminal_requisition;
   GtkRequisition window_requisition;
   gint           width;
   gint           height;
-  glong          columns;
-  glong          rows;
-  gint           xpad = 0;
-  gint           ypad = 0;
-  GtkBorder     *border = NULL;
+  gint           xpad, ypad;
+  glong          char_width;
+  glong          char_height;
+
 
   terminal_return_if_fail (TERMINAL_IS_SCREEN (screen));
   terminal_return_if_fail (VTE_IS_TERMINAL (screen->terminal));
@@ -1725,29 +1756,24 @@ terminal_screen_force_resize_window (TerminalScreen *screen,
   gtk_widget_size_request (GTK_WIDGET (window), &window_requisition);
   gtk_widget_size_request (screen->terminal, &terminal_requisition);
 
-  width = MAX (window_requisition.width - terminal_requisition.width, 0);
-  height = MAX (window_requisition.height - terminal_requisition.height, 0);
-
-  if (force_columns < 0)
-    columns = VTE_TERMINAL (screen->terminal)->column_count;
-  else
-    columns = force_columns;
+  if (columns < 1)
+    columns = vte_terminal_get_column_count (VTE_TERMINAL (screen->terminal));
+  if (rows < 1)
+    rows = vte_terminal_get_row_count (VTE_TERMINAL (screen->terminal));
 
-  if (force_rows < 0)
-    rows = VTE_TERMINAL (screen->terminal)->row_count;
-  else
-    rows = force_rows;
+  terminal_screen_get_geometry (screen,
+                                &char_width, &char_height,
+                                &xpad, &ypad);
 
-  gtk_widget_style_get (GTK_WIDGET (screen->terminal), "inner-border", &border, NULL);
-  if (border != NULL)
-    {
-      xpad = border->left + border->right;
-      ypad = border->top + border->bottom;
-      gtk_border_free (border);
-    }
+  width = window_requisition.width - terminal_requisition.width;
+  if (width < 0)
+    width = 0;
+  width += xpad + char_width * columns;
 
-  width += xpad + VTE_TERMINAL (screen->terminal)->char_width * columns;
-  height += ypad + VTE_TERMINAL (screen->terminal)->char_height * rows;
+  height = window_requisition.height - terminal_requisition.height;
+  if (height < 0)
+    height = 0;
+  height += ypad + char_height * rows;
 
   if (GTK_WIDGET_MAPPED (window))
     gtk_window_resize (window, width, height);
@@ -2107,9 +2133,8 @@ terminal_screen_reset_activity (TerminalScreen *screen)
 GtkWidget *
 terminal_screen_get_tab_label (TerminalScreen *screen)
 {
-  GtkWidget  *hbox;
-  GtkWidget  *button, *image, *align;
-  GtkRcStyle *style;
+  GtkWidget *hbox;
+  GtkWidget *button, *image, *align;
 
   terminal_return_val_if_fail (TERMINAL_IS_SCREEN (screen), NULL);
 
@@ -2147,10 +2172,7 @@ terminal_screen_get_tab_label (TerminalScreen *screen)
   gtk_widget_show (button);
 
   /* make button a bit smaller */
-  style = gtk_rc_style_new ();
-  style->xthickness = style->ythickness = 0;
-  gtk_widget_modify_style (button, style);
-  g_object_unref (G_OBJECT (style));
+  terminal_set_style_thinkess (button, 0);
 
   /* button image */
   image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
diff --git a/terminal/terminal-screen.h b/terminal/terminal-screen.h
index 1a03a42..b4f2cb3 100644
--- a/terminal/terminal-screen.h
+++ b/terminal/terminal-screen.h
@@ -51,6 +51,12 @@ void         terminal_screen_set_size                     (TerminalScreen *scree
                                                            glong           width_chars,
                                                            glong           height_chars);
 
+void         terminal_screen_get_geometry                 (TerminalScreen *screen,
+                                                           glong          *char_width,
+                                                           glong          *char_height,
+                                                           gint           *xpad,
+                                                           gint           *ypad);
+
 void         terminal_screen_set_window_geometry_hints    (TerminalScreen *screen,
                                                            GtkWindow      *window);
 
diff --git a/terminal/terminal-search-dialog.c b/terminal/terminal-search-dialog.c
index ef3cdb7..a7b08c6 100644
--- a/terminal/terminal-search-dialog.c
+++ b/terminal/terminal-search-dialog.c
@@ -55,7 +55,7 @@ struct _TerminalSearchDialog
 
   GtkWidget *button_prev;
   GtkWidget *button_next;
-  
+
   GtkWidget *entry;
 
   GtkWidget *match_case;
@@ -96,19 +96,24 @@ terminal_search_dialog_init (TerminalSearchDialog *dialog)
   dialog->button_prev = xfce_gtk_button_new_mixed (GTK_STOCK_GO_BACK, _("_Previous"));
   gtk_dialog_add_action_widget (GTK_DIALOG (dialog), dialog->button_prev, TERMINAL_RESPONSE_SEARCH_PREV);
   gtk_widget_set_can_default (dialog->button_prev, TRUE);
+  gtk_widget_show (dialog->button_prev);
 
   dialog->button_next = xfce_gtk_button_new_mixed (GTK_STOCK_GO_FORWARD, _("_Next"));
   gtk_dialog_add_action_widget (GTK_DIALOG (dialog), dialog->button_next, TERMINAL_RESPONSE_SEARCH_NEXT);
+  gtk_widget_show (dialog->button_next);
 
   vbox = gtk_vbox_new (FALSE, 6);
   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), vbox, TRUE, TRUE, 0);
   gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
+  gtk_widget_show (vbox);
 
   hbox = gtk_hbox_new (FALSE, 12);
   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+  gtk_widget_show (hbox);
 
   label = gtk_label_new_with_mnemonic (_("_Search for:"));
   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
 
   dialog->entry = gtk_entry_new ();
   gtk_box_pack_start (GTK_BOX (hbox), dialog->entry, TRUE, TRUE, 0);
@@ -119,26 +124,31 @@ terminal_search_dialog_init (TerminalSearchDialog *dialog)
       G_CALLBACK (terminal_search_dialog_entry_icon_release), NULL);
   g_signal_connect (G_OBJECT (dialog->entry), "changed",
       G_CALLBACK (terminal_search_dialog_entry_changed), dialog);
+  gtk_widget_show (dialog->entry);
 
   dialog->match_case = gtk_check_button_new_with_mnemonic (_("C_ase sensitive"));
   gtk_box_pack_start (GTK_BOX (vbox), dialog->match_case, FALSE, FALSE, 0);
   g_signal_connect_swapped (G_OBJECT (dialog->match_case), "toggled",
       G_CALLBACK (terminal_search_dialog_clear_gregex), dialog);
+  gtk_widget_show (dialog->match_case);
 
   dialog->match_regex = gtk_check_button_new_with_mnemonic (_("Match as _regular expression"));
   gtk_box_pack_start (GTK_BOX (vbox), dialog->match_regex, FALSE, FALSE, 0);
   g_signal_connect_swapped (G_OBJECT (dialog->match_regex), "toggled",
       G_CALLBACK (terminal_search_dialog_clear_gregex), dialog);
+  gtk_widget_show (dialog->match_regex);
 
   dialog->match_word = gtk_check_button_new_with_mnemonic (_("Match _entire word only"));
   gtk_box_pack_start (GTK_BOX (vbox), dialog->match_word, FALSE, FALSE, 0);
   g_signal_connect_swapped (G_OBJECT (dialog->match_word), "toggled",
       G_CALLBACK (terminal_search_dialog_clear_gregex), dialog);
+  gtk_widget_show (dialog->match_word);
 
   dialog->wrap_around = gtk_check_button_new_with_mnemonic (_("_Wrap around"));
   gtk_box_pack_start (GTK_BOX (vbox), dialog->wrap_around, FALSE, FALSE, 0);
   g_signal_connect_swapped (G_OBJECT (dialog->wrap_around), "toggled",
       G_CALLBACK (terminal_search_dialog_clear_gregex), dialog);
+  gtk_widget_show (dialog->wrap_around);
 
   terminal_search_dialog_entry_changed (dialog->entry, dialog);
 }
diff --git a/terminal/terminal-window-dropdown.c b/terminal/terminal-window-dropdown.c
new file mode 100644
index 0000000..e02a5fa
--- /dev/null
+++ b/terminal/terminal-window-dropdown.c
@@ -0,0 +1,338 @@
+/*-
+ * Copyright (C) 2012 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA.
+ *
+ * The geometry handling code was taken from gnome-terminal. The geometry hacks
+ * were initially written by Owen Taylor.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <libxfce4ui/libxfce4ui.h>
+
+#include <terminal/terminal-private.h>
+#include <terminal/terminal-window.h>
+#include <terminal/terminal-dialogs.h>
+#include <terminal/terminal-window-dropdown.h>
+
+
+
+static void            terminal_window_dropdown_finalize                      (GObject                *object);
+static gboolean        terminal_window_dropdown_focus_out_event               (GtkWidget              *widget,
+                                                                               GdkEventFocus          *event);
+static void            terminal_window_dropdown_position                      (TerminalWindowDropdown *dropdown);
+static void            terminal_window_dropdown_preferences                   (TerminalWindowDropdown *dropdown);
+
+
+typedef enum
+{
+  DROPDOWN_STATE_HIDDEN,
+  DROPDOWN_STATE_VISIBLE,
+}
+DropdownState;
+
+struct _TerminalWindowDropdownClass
+{
+  TerminalWindowClass __parent__;
+};
+
+struct _TerminalWindowDropdown
+{
+  TerminalWindow __parent__;
+
+  /* ui widgets */
+  GtkWidget     *keep_open;
+
+  /* size */
+  gdouble        rel_width;
+  gdouble        rel_height;
+};
+
+
+
+G_DEFINE_TYPE (TerminalWindowDropdown, terminal_window_dropdown, TERMINAL_TYPE_WINDOW)
+
+
+
+static void
+terminal_window_dropdown_class_init (TerminalWindowDropdownClass *klass)
+{
+  GObjectClass   *gobject_class;
+  GtkWidgetClass *gtkwidget_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = terminal_window_dropdown_finalize;
+
+  gtkwidget_class = GTK_WIDGET_CLASS (klass);
+  gtkwidget_class->focus_out_event = terminal_window_dropdown_focus_out_event;
+}
+
+
+
+static void
+terminal_window_dropdown_init (TerminalWindowDropdown *dropdown)
+{
+  TerminalWindow *window = TERMINAL_WINDOW (dropdown);
+  GtkAction      *action;
+  GtkWidget      *hbox;
+  GtkWidget      *button;
+  GtkWidget      *img;
+
+  /* shared setting to disable some functionality in TerminalWindow */
+  window->drop_down = TRUE;
+
+  dropdown->rel_width = 0.8;
+  dropdown->rel_height = 0.6;
+
+  /* default window settings */
+  gtk_window_set_resizable (GTK_WINDOW (dropdown), FALSE);
+  gtk_window_set_decorated (GTK_WINDOW (dropdown), FALSE);
+  gtk_window_set_keep_above (GTK_WINDOW (dropdown), TRUE);
+  gtk_window_set_gravity (GTK_WINDOW (dropdown), GDK_GRAVITY_STATIC);
+  gtk_window_set_type_hint  (GTK_WINDOW (dropdown), GDK_WINDOW_TYPE_HINT_DIALOG); /* avoid smart placement */
+  gtk_window_set_opacity (GTK_WINDOW (dropdown), 0.85);
+  gtk_window_stick (GTK_WINDOW (dropdown));
+
+  /* this avoids to return focus to the window after dialog changes,
+   * but we have terminal_activate_window() for that */
+  gtk_window_set_skip_pager_hint (GTK_WINDOW (dropdown), TRUE);
+  gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dropdown), TRUE);
+
+  /* adjust notebook for drop-down usage */
+  gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->notebook), TRUE);
+  gtk_notebook_set_tab_pos (GTK_NOTEBOOK (window->notebook), GTK_POS_BOTTOM);
+  terminal_set_style_thinkess (window->notebook, 1);
+
+  /* actions we don't want */
+  action = gtk_action_group_get_action (window->action_group, "show-borders");
+  gtk_action_set_visible (action, FALSE);
+
+  /* notebook buttons */
+  hbox = gtk_hbox_new (TRUE, 2);
+  gtk_notebook_set_action_widget (GTK_NOTEBOOK (window->notebook), hbox, GTK_PACK_END);
+  gtk_widget_show (hbox);
+
+  button = dropdown->keep_open = gtk_toggle_button_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+  gtk_widget_set_tooltip_text (button, _("Keep window open when it loses focus"));
+  gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+  gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
+  gtk_widget_show (button);
+
+  img = gtk_image_new_from_stock (GTK_STOCK_GOTO_BOTTOM, GTK_ICON_SIZE_MENU);
+  gtk_container_add (GTK_CONTAINER (button), img);
+  gtk_widget_show (img);
+
+  button = gtk_button_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+  gtk_widget_set_tooltip_text (button, _("Drop-down Preferences..."));
+  gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+  gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
+  g_signal_connect_swapped (G_OBJECT (button), "clicked",
+      G_CALLBACK (terminal_window_dropdown_preferences), dropdown);
+  gtk_widget_show (button);
+
+  img = gtk_image_new_from_stock (GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU);
+  gtk_container_add (GTK_CONTAINER (button), img);
+  gtk_widget_show (img);
+}
+
+
+
+static void
+terminal_window_dropdown_finalize (GObject *object)
+{
+  //TerminalWindowDropdown *dropdown = TERMINAL_WINDOW_DROPDOWN (object);
+
+  (*G_OBJECT_CLASS (terminal_window_dropdown_parent_class)->finalize) (object);
+}
+
+
+
+static gboolean
+terminal_window_dropdown_focus_out_event (GtkWidget     *widget,
+                                          GdkEventFocus *event)
+{
+  TerminalWindowDropdown *dropdown = TERMINAL_WINDOW_DROPDOWN (widget);
+  gboolean                retval;
+  GdkGrabStatus           status;
+
+  /* let Gtk do its thingy */
+  retval = (*GTK_WIDGET_CLASS (terminal_window_dropdown_parent_class)->focus_out_event) (widget, event);
+
+  /* check if keep open is not enabled */
+  if (gtk_widget_get_visible (widget)
+      && TERMINAL_WINDOW (dropdown)->n_child_windows == 0
+      && gtk_grab_get_current () == NULL /* popup menu check */
+      && !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dropdown->keep_open)))
+    {
+      /* check if the user is not pressing a key */
+      status = gdk_keyboard_grab (event->window, FALSE, GDK_CURRENT_TIME);
+      if (status == GDK_GRAB_SUCCESS)
+        {
+          /* drop the grab */
+          gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+
+          /* hide the window */
+          gtk_widget_hide (GTK_WIDGET (dropdown));
+        }
+    }
+
+  return retval;
+}
+
+
+
+static void
+terminal_window_dropdown_position (TerminalWindowDropdown *dropdown)
+{
+  TerminalWindow *window = TERMINAL_WINDOW (dropdown);
+  gint            w, h;
+  GdkRectangle    monitor_geo;
+  gint            x_dest, y_dest;
+  GdkScreen      *screen;
+  gint            monitor_num;
+  gint            xpad, ypad;
+  glong           char_width, char_height;
+  GtkRequisition  req1, req2;
+
+  /* nothing to do if the window is hidden */
+  if (!gtk_widget_get_visible (GTK_WIDGET (dropdown)))
+    return;
+
+  /* get the active monitor size */
+  screen = xfce_gdk_screen_get_active (&monitor_num);
+  gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor_geo);
+
+  /* move window to correct screen */
+  gtk_window_set_screen (GTK_WINDOW (dropdown), screen);
+
+  /* calculate size */
+  w = monitor_geo.width * dropdown->rel_width;
+  h = monitor_geo.height * dropdown->rel_height;
+
+  /* get terminal size */
+  terminal_screen_get_geometry (window->active, &char_width, &char_height, &xpad, &ypad);
+
+  /* correct padding with notebook size */
+  gtk_widget_size_request (GTK_WIDGET (window->notebook), &req1);
+  gtk_widget_size_request (GTK_WIDGET (window->active), &req2);
+  xpad += MAX (req1.width - req2.width, 0);
+  ypad += MAX (req1.height - req2.height, 0);
+
+  /* minimize to fit terminal charaters */
+  w -= (w - xpad) % char_width;
+  h -= (h - ypad) % char_height;
+
+  /* resize the notebook */
+  gtk_widget_set_size_request (window->notebook, w, h);
+
+  /* calc position */
+  x_dest = monitor_geo.x + (monitor_geo.width - w) / 2;
+  y_dest = monitor_geo.y;
+
+  /* move */
+  gtk_window_move (GTK_WINDOW (dropdown), x_dest, y_dest);
+}
+
+
+
+static void
+terminal_window_dropdown_preferences (TerminalWindowDropdown *dropdown)
+{
+
+}
+
+
+
+static guint32
+terminal_window_dropdown_get_timestamp (GtkWidget   *widget,
+                                        const gchar *startup_id)
+{
+  const gchar *timestr;
+  guint32      timestamp;
+  gchar       *end;
+
+  /* extract the time from the id */
+  if (startup_id != NULL)
+    {
+      timestr = g_strrstr (startup_id, "_TIME");
+      if (G_LIKELY (timestr != NULL))
+        {
+          timestr += 5;
+          errno = 0;
+
+          /* translate into integer */
+          timestamp = strtoul (timestr, &end, 0);
+          if (end != timestr && errno == 0)
+            return timestamp;
+        }
+    }
+
+  return GDK_CURRENT_TIME;
+}
+
+
+
+GtkWidget *
+terminal_window_dropdown_new (void)
+{
+  return g_object_new (TERMINAL_TYPE_WINDOW_DROPDOWN, NULL);
+}
+
+
+
+void
+terminal_window_dropdown_toggle (TerminalWindowDropdown *dropdown,
+                                 const gchar            *startup_id)
+{
+  guint32 timestamp;
+
+  if (gtk_widget_get_visible (GTK_WIDGET (dropdown)))
+    {
+      /* hide */
+      gtk_widget_hide (GTK_WIDGET (dropdown));
+    }
+  else
+    {
+      /* show with event time */
+      timestamp = terminal_window_dropdown_get_timestamp (GTK_WIDGET (dropdown), startup_id);
+      gtk_window_present_with_time (GTK_WINDOW (dropdown), timestamp);
+
+      /* check position */
+      terminal_window_dropdown_position (dropdown);
+    }
+
+  /* window is focussed or hidden */
+  if (startup_id != NULL)
+    gdk_notify_startup_complete_with_id (startup_id);
+}
diff --git a/terminal/terminal-window-dropdown.h b/terminal/terminal-window-dropdown.h
new file mode 100644
index 0000000..b8dffab
--- /dev/null
+++ b/terminal/terminal-window-dropdown.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (C) 2012 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __TERMINAL_WINDOW_DROPDOWN_DROPDOWN_H__
+#define __TERMINAL_WINDOW_DROPDOWN_DROPDOWN_H__
+
+#include <terminal/terminal-screen.h>
+#include <terminal/terminal-options.h>
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_WINDOW_DROPDOWN            (terminal_window_dropdown_get_type ())
+#define TERMINAL_WINDOW_DROPDOWN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TERMINAL_TYPE_WINDOW_DROPDOWN, TerminalWindowDropdown))
+#define TERMINAL_WINDOW_DROPDOWN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TERMINAL_TYPE_WINDOW_DROPDOWN, TerminalWindowDropdownClass))
+#define TERMINAL_IS_WINDOW_DROPDOWN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TERMINAL_TYPE_WINDOW_DROPDOWN))
+#define TERMINAL_IS_WINDOW_DROPDOWN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TERMINAL_TYPE_WINDOW_DROPDOWN))
+#define TERMINAL_WINDOW_DROPDOWN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), TERMINAL_TYPE_WINDOW_DROPDOWN, TerminalWindowDropdownClass))
+
+typedef struct _TerminalWindowDropdownClass TerminalWindowDropdownClass;
+typedef struct _TerminalWindowDropdown      TerminalWindowDropdown;
+
+GType           terminal_window_dropdown_get_type             (void) G_GNUC_CONST;
+
+GtkWidget      *terminal_window_dropdown_new                  (void);
+
+void            terminal_window_dropdown_toggle               (TerminalWindowDropdown *dropdown,
+                                                               const gchar            *startup_id);
+
+G_END_DECLS
+
+#endif /* !__TERMINAL_WINDOW_DROPDOWN_H__ */
diff --git a/terminal/terminal-window.c b/terminal/terminal-window.c
index 33610ba..b644002 100644
--- a/terminal/terminal-window.c
+++ b/terminal/terminal-window.c
@@ -191,52 +191,6 @@ static void            terminal_window_action_about                  (GtkAction
 
 
 
-struct _TerminalWindowClass
-{
-  GtkWindowClass __parent__;
-};
-
-struct _TerminalWindow
-{
-  GtkWindow            __parent__;
-
-  TerminalPreferences *preferences;
-  GtkWidget           *preferences_dialog;
-
-  GtkActionGroup      *action_group;
-  GtkUIManager        *ui_manager;
-
-  guint                tabs_menu_merge_id;
-  GSList              *tabs_menu_actions;
-
-  GtkWidget           *menubar;
-  GtkWidget           *toolbar;
-  GtkWidget           *notebook;
-
-  GtkWidget           *search_dialog;
-
-  /* pushed size of screen */
-  glong                grid_width;
-  glong                grid_height;
-
-  GtkAction           *encoding_action;
-
-  TerminalScreen      *active;
-
-  /* cached actions to avoid lookups */
-  GtkAction           *action_detah_tab;
-  GtkAction           *action_close_tab;
-  GtkAction           *action_prev_tab;
-  GtkAction           *action_next_tab;
-  GtkAction           *action_move_tab_left;
-  GtkAction           *action_move_tab_right;
-  GtkAction           *action_copy;
-  GtkAction           *action_search_next;
-  GtkAction           *action_search_prev;
-};
-
-
-
 static guint         window_signals[LAST_SIGNAL];
 static gconstpointer window_notebook_group = PACKAGE_NAME;
 static GQuark        tabs_menu_action_quark = 0;
@@ -343,7 +297,6 @@ terminal_window_init (TerminalWindow *window)
   GtkAction      *action;
   GtkWidget      *vbox;
   gboolean        always_show_tabs;
-  GtkRcStyle     *style;
   GdkScreen      *screen;
   GdkColormap    *colormap;
 
@@ -399,15 +352,9 @@ terminal_window_init (TerminalWindow *window)
                                    "tab-hborder", 0,
                                    "tab-vborder", 0,
                                    NULL);
-  g_object_bind_property (G_OBJECT (window->preferences), "misc-tab-position",
-                          G_OBJECT (window->notebook), "tab-pos",
-                          G_BINDING_SYNC_CREATE);
 
   /* hide the ugly terminal border when tabs are shown */
-  style = gtk_rc_style_new ();
-  style->xthickness = style->ythickness = 0;
-  gtk_widget_modify_style (window->notebook, style);
-  g_object_unref (G_OBJECT (style));
+  terminal_set_style_thinkess (window->notebook, 0);
 
   /* set the notebook group id */
   gtk_notebook_set_group (GTK_NOTEBOOK (window->notebook),
@@ -681,7 +628,8 @@ terminal_window_set_size_force_grid (TerminalWindow *window,
   terminal_return_if_fail (TERMINAL_IS_SCREEN (screen));
 
   /* required to get the char height/width right */
-  if (gtk_widget_get_realized (GTK_WIDGET (screen)))
+  if (gtk_widget_get_realized (GTK_WIDGET (screen))
+      && !window->drop_down)
     {
       terminal_screen_force_resize_window (screen, GTK_WINDOW (window),
                                            force_grid_width, force_grid_height);
@@ -902,6 +850,10 @@ terminal_window_notebook_show_tabs (TerminalWindow *window)
   gboolean     show_tabs = TRUE;
   gint         npages;
 
+  /* handled by other widget */
+  if (window->drop_down)
+    return;
+
   /* set the visibility of the tabs */
   npages = gtk_notebook_get_n_pages (notebook);
   if (npages < 2)
@@ -1614,9 +1566,9 @@ terminal_window_action_goto_tab (GtkRadioAction *action,
 
 
 static void
-title_dialog_response (GtkWidget *dialog,
-                       gint       response,
-                       GBinding  *title_binding)
+title_dialog_response (GtkWidget      *dialog,
+                       gint            response,
+                       TerminalWindow *window)
 {
   /* check if we should open the user manual */
   if (response == GTK_RESPONSE_HELP)
@@ -1626,8 +1578,12 @@ title_dialog_response (GtkWidget *dialog,
     }
   else
     {
+      /* need for hiding on focus */
+      if (window->drop_down)
+        terminal_activate_window (GTK_WINDOW (window));
+
       /* close the dialog */
-      g_object_unref (title_binding);
+      window->n_child_windows--;
       gtk_widget_destroy (dialog);
     }
 }
@@ -1635,9 +1591,11 @@ title_dialog_response (GtkWidget *dialog,
 
 
 static void
-title_dialog_quit (GtkWidget *dialog)
+title_dialog_clear (GtkWidget            *entry,
+                    GtkEntryIconPosition  icon_pos)
 {
-  gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
+  if (icon_pos == GTK_ENTRY_ICON_SECONDARY)
+    gtk_entry_set_text (GTK_ENTRY (entry), "");
 }
 
 
@@ -1646,54 +1604,51 @@ static void
 terminal_window_action_set_title (GtkAction      *action,
                                   TerminalWindow *window)
 {
-  AtkRelationSet   *relations;
-  AtkRelation      *relation;
-  AtkObject        *object;
-  GtkWidget        *dialog;
-  GtkWidget        *box;
-  GtkWidget        *label;
-  GtkWidget        *entry;
-  GBinding         *title_binding;
+  AtkObject *object;
+  GtkWidget *dialog;
+  GtkWidget *box;
+  GtkWidget *label;
+  GtkWidget *entry;
 
   if (G_LIKELY (window->active != NULL))
     {
+      window->n_child_windows++;
+
       dialog = gtk_dialog_new_with_buttons (Q_("Window Title|Set Title"),
                                             GTK_WINDOW (window),
-                                            GTK_DIALOG_DESTROY_WITH_PARENT
-                                            | GTK_DIALOG_NO_SEPARATOR,
+                                            GTK_DIALOG_DESTROY_WITH_PARENT,
                                             GTK_STOCK_HELP, GTK_RESPONSE_HELP,
                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
                                             NULL);
+      gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
 
       box = gtk_hbox_new (FALSE, 12);
       gtk_container_set_border_width (GTK_CONTAINER (box), 6);
       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), box, TRUE, TRUE, 0);
       gtk_widget_show (box);
 
-      label = gtk_label_new (_("Title:"));
+      label = gtk_label_new_with_mnemonic (_("_Title:"));
       gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0);
       gtk_widget_show (label);
 
       entry = gtk_entry_new ();
       gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 0);
-      g_signal_connect_swapped (G_OBJECT (entry), "activate",
-                                G_CALLBACK (title_dialog_quit), dialog);
+      gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
+      gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+      gtk_entry_set_icon_from_stock (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
+      g_signal_connect (G_OBJECT (entry), "icon-release", G_CALLBACK (title_dialog_clear), NULL);
       gtk_widget_show (entry);
 
       /* set Atk description and label relation for the entry */
       object = gtk_widget_get_accessible (entry);
       atk_object_set_description (object, _("Enter the title for the current terminal tab"));
-      relations = atk_object_ref_relation_set (gtk_widget_get_accessible (label));
-      relation = atk_relation_new (&object, 1, ATK_RELATION_LABEL_FOR);
-      atk_relation_set_add (relations, relation);
-      g_object_unref (G_OBJECT (relation));
 
-      title_binding = g_object_bind_property (G_OBJECT (window->active), "custom-title",
-                                              G_OBJECT (entry), "text",
-                                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+      g_object_bind_property (G_OBJECT (window->active), "custom-title",
+                              G_OBJECT (entry), "text",
+                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
 
       g_signal_connect (G_OBJECT (dialog), "response",
-                        G_CALLBACK (title_dialog_response), title_binding);
+                        G_CALLBACK (title_dialog_response), window);
 
       gtk_widget_show (dialog);
     }
@@ -1740,7 +1695,12 @@ terminal_window_action_search_response (GtkWidget      *dialog,
     }
   else
     {
+      /* need for hiding on focus */
+      if (window->drop_down)
+        terminal_activate_window (GTK_WINDOW (window));
+
       /* hide dialog */
+      window->n_child_windows--;
       gtk_widget_hide (dialog);
     }
 
@@ -1761,9 +1721,12 @@ terminal_window_action_search (GtkAction      *action,
       window->search_dialog = terminal_search_dialog_new (GTK_WINDOW (window));
       g_signal_connect (G_OBJECT (window->search_dialog), "response",
           G_CALLBACK (terminal_window_action_search_response), window);
-      gtk_widget_show_all (window->search_dialog);
     }
 
+  /* increase child counter */
+  if (!gtk_widget_get_visible (window->search_dialog))
+    window->n_child_windows++;
+
   terminal_search_dialog_present (TERMINAL_SEARCH_DIALOG (window->search_dialog));
 }
 
@@ -1896,6 +1859,11 @@ terminal_window_new (const gchar       *role,
   action = gtk_action_group_get_action (window->action_group, "show-borders");
   gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), show_borders);
 
+  /* property that is not suitable for init */
+  g_object_bind_property (G_OBJECT (window->preferences), "misc-tab-position",
+                          G_OBJECT (window->notebook), "tab-pos",
+                          G_BINDING_SYNC_CREATE);
+
   return GTK_WIDGET (window);
 }
 
diff --git a/terminal/terminal-window.h b/terminal/terminal-window.h
index f877519..ed804f5 100644
--- a/terminal/terminal-window.h
+++ b/terminal/terminal-window.h
@@ -23,6 +23,7 @@
 
 #include <terminal/terminal-screen.h>
 #include <terminal/terminal-options.h>
+#include <terminal/terminal-preferences.h>
 
 G_BEGIN_DECLS
 
@@ -36,6 +37,56 @@ G_BEGIN_DECLS
 typedef struct _TerminalWindowClass TerminalWindowClass;
 typedef struct _TerminalWindow      TerminalWindow;
 
+struct _TerminalWindowClass
+{
+  GtkWindowClass __parent__;
+};
+
+struct _TerminalWindow
+{
+  GtkWindow            __parent__;
+
+  /* if this is a TerminalWindowDropdown */
+  guint                drop_down : 1;
+
+  /* for the drop-down to keep open with dialogs */
+  guint                n_child_windows;
+
+  TerminalPreferences *preferences;
+  GtkWidget           *preferences_dialog;
+
+  GtkActionGroup      *action_group;
+  GtkUIManager        *ui_manager;
+
+  guint                tabs_menu_merge_id;
+  GSList              *tabs_menu_actions;
+
+  GtkWidget           *menubar;
+  GtkWidget           *toolbar;
+  GtkWidget           *notebook;
+
+  GtkWidget           *search_dialog;
+
+  /* pushed size of screen */
+  glong                grid_width;
+  glong                grid_height;
+
+  GtkAction           *encoding_action;
+
+  TerminalScreen      *active;
+
+  /* cached actions to avoid lookups */
+  GtkAction           *action_detah_tab;
+  GtkAction           *action_close_tab;
+  GtkAction           *action_prev_tab;
+  GtkAction           *action_next_tab;
+  GtkAction           *action_move_tab_left;
+  GtkAction           *action_move_tab_right;
+  GtkAction           *action_copy;
+  GtkAction           *action_search_next;
+  GtkAction           *action_search_prev;
+};
+
 GType           terminal_window_get_type             (void) G_GNUC_CONST;
 
 GtkWidget      *terminal_window_new                  (const gchar        *role,


More information about the Xfce4-commits mailing list