emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/pgtk 28073ba 083/100: Re-implement childframe with emacsgtkfixed


From: Yuuki Harano
Subject: feature/pgtk 28073ba 083/100: Re-implement childframe with emacsgtkfixed
Date: Tue, 24 Nov 2020 08:02:43 -0500 (EST)

branch: feature/pgtk
commit 28073ba59bbabec1194977d654b471800ce63f45
Author: Yuuki Harano <masm+github@masm11.me>
Commit: Jeff Walsh <jeff.walsh@drtusers-MacBook-Pro.local>

    Re-implement childframe with emacsgtkfixed
    
    * src/emacsgtkfixed.c (G_DEFINE_TYPE): Make emacs_fixed_get_type public.
    * src/emacsgtkfixed.h (EMACS_TYPE_FIXED): Make emacs_fixed_get_type public.
    * src/gtkutil.c (xg_frame_set_char_size): Call appropriate functions
    by whether the frame is a child frame or not.
    (xg_create_frame_widgets): Use GTK_WINDOW_TOPLEVEL when creating child 
frame.
    (xg_create_frame_outer_widgets): New function.
    (xg_set_skip_taskbar): Call only when top-level frame.
    (xg_set_no_accept_focus): See appropriate widget.
    * src/gtkutil.h: New declaration.
    * src/pgtkfns.c (pgtk_set_name_internal): Do only when top-level frame.
    (Fx_create_frame): Reparent the frame.
    (frame_geometry): Call appropriate functions
    (syms_of_pgtkfns): Port from X code.
    * src/pgtkterm.c (x_free_frame_resources): Destroy appropriate widget.
    (x_calc_absolute_position): Port from X code.
    (x_set_offset): Re-port from X code.
    (pgtk_set_window_size): Use appropriate widget.
    (pgtk_make_frame_visible): Use appropriate widget.
    (pgtk_make_frame_invisible): Use appropriate widget.
    (x_set_parent_frame): Reparent the frame.
    (x_set_z_group): Process only when top-level frame.
    (pgtk_text_icon): Process only when top-level frame.
    (set_fullscreen_state): Process only when top-level frame.
    (frame_highlight): Hold ref.
    (frame_unhighlight): Hold ref.
    (pgtk_window_is_of_frame_recursive): Prune child frames.
    (pgtk_window_is_of_frame): Prune child frames.
    (print_widget_tree_recursive): Don't call this when not debugging.
    (pgtk_handle_draw): Don't call this when not debugging.
    (pgtk_set_event_handler): expect map-event for edit_widget not outer widget.
    * src/pgtkterm.h (FRAME_WIDGET): New macro.
---
 src/emacsgtkfixed.c |   1 -
 src/emacsgtkfixed.h |   5 +
 src/gtkutil.c       | 162 ++++++++++++++++++++++++++-
 src/gtkutil.h       |   3 +
 src/pgtkfns.c       |  67 ++++++++++--
 src/pgtkterm.c      | 307 +++++++++++++++++++++++++++++++++++++++++-----------
 src/pgtkterm.h      |   3 +
 7 files changed, 465 insertions(+), 83 deletions(-)

diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c
index 4128f81..d2a7fcb 100644
--- a/src/emacsgtkfixed.c
+++ b/src/emacsgtkfixed.c
@@ -51,7 +51,6 @@ static void emacs_fixed_get_preferred_width  (GtkWidget 
*widget,
 static void emacs_fixed_get_preferred_height (GtkWidget *widget,
                                               gint      *minimum,
                                               gint      *natural);
-static GType emacs_fixed_get_type (void);
 G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED)
 
 static EmacsFixed *
diff --git a/src/emacsgtkfixed.h b/src/emacsgtkfixed.h
index b230a4d..f2fb1f2 100644
--- a/src/emacsgtkfixed.h
+++ b/src/emacsgtkfixed.h
@@ -27,6 +27,9 @@ struct frame;
 
 G_BEGIN_DECLS
 
+#define EMACS_TYPE_FIXED        (emacs_fixed_get_type ())
+#define EMACS_IS_FIXED(obj)     (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
EMACS_TYPE_FIXED))
+
 struct frame;
 
 typedef struct _EmacsFixedPrivate       EmacsFixedPrivate;
@@ -44,6 +47,8 @@ struct _EmacsFixedClass
   GtkFixedClass parent_class;
 };
 
+extern GType emacs_fixed_get_type (void);
+
 extern GtkWidget *emacs_fixed_new (struct frame *f);
 
 G_END_DECLS
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 3956c58..0f1a51f 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1060,8 +1060,20 @@ xg_frame_set_char_size (struct frame *f, int width, int 
height)
   if (FRAME_PIXEL_HEIGHT (f) == 0)
     return;
 
+#ifndef HAVE_PGTK
   gtk_window_get_size (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
                       &gwidth, &gheight);
+#else
+  if (FRAME_GTK_OUTER_WIDGET (f)) {
+    gtk_window_get_size (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+                        &gwidth, &gheight);
+  } else {
+    GtkAllocation alloc;
+    gtk_widget_get_allocation (FRAME_GTK_WIDGET (f), &alloc);
+    gwidth = alloc.width;
+    gheight = alloc.height;
+  }
+#endif
 
   /* Do this before resize, as we don't know yet if we will be resized.  */
   FRAME_RIF (f)->clear_under_internal_border (f);
@@ -1101,11 +1113,7 @@ xg_frame_set_char_size (struct frame *f, int width, int 
height)
   else if (FRAME_PARENT_FRAME (f) && FRAME_VISIBLE_P (f))
     {
       was_visible = true;
-#ifndef HAVE_PGTK
       hide_child_frame = EQ (x_gtk_resize_child_frames, Qhide);
-#else
-      hide_child_frame = true;
-#endif // !HAVE_PGTK
 
       if (totalwidth != gwidth || totalheight != gheight)
        {
@@ -1116,17 +1124,35 @@ xg_frame_set_char_size (struct frame *f, int width, int 
height)
           if (hide_child_frame)
             {
               block_input ();
+#ifndef HAVE_PGTK
               gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
+#else
+             gtk_widget_hide (FRAME_WIDGET (f));
+#endif
               unblock_input ();
             }
 
+#ifndef HAVE_PGTK
          gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
                             totalwidth, totalheight);
+#else
+         if (FRAME_GTK_OUTER_WIDGET (f)) {
+           gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+                              totalwidth, totalheight);
+         } else {
+           gtk_widget_set_size_request (FRAME_GTK_WIDGET (f),
+                                        totalwidth, totalheight);
+         }
+#endif
 
           if (hide_child_frame)
             {
               block_input ();
+#ifndef HAVE_PGTK
               gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
+#else
+             gtk_widget_show_all (FRAME_WIDGET (f));
+#endif
               unblock_input ();
             }
 
@@ -1138,8 +1164,18 @@ xg_frame_set_char_size (struct frame *f, int width, int 
height)
       frame_size_history_add
        (f, Qxg_frame_set_char_size_3, width, height,
         list2i (totalwidth, totalheight));
+#ifndef HAVE_PGTK
       gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
                         totalwidth, totalheight);
+#else
+      if (FRAME_GTK_OUTER_WIDGET (f)) {
+       gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+                          totalwidth, totalheight);
+      } else {
+       gtk_widget_set_size_request (FRAME_GTK_WIDGET (f),
+                                    totalwidth, totalheight);
+      }
+#endif
       fullscreen = Qnil;
     }
 
@@ -1355,7 +1391,7 @@ xg_create_frame_widgets (struct frame *f)
   else
     wtop = gtk_window_new (type);
 #else
-  if (!NILP(f->parent_frame) || f->tooltip)
+  if (f->tooltip)
     {
       type = GTK_WINDOW_POPUP;
     }
@@ -1546,6 +1582,107 @@ xg_create_frame_widgets (struct frame *f)
   return 1;
 }
 
+#ifdef HAVE_PGTK
+void
+xg_create_frame_outer_widgets (struct frame *f)
+{
+  GtkWidget *wtop;
+  GtkWidget *wvbox, *whbox;
+  GtkWindowType type = GTK_WINDOW_TOPLEVEL;
+  char *title = 0;
+
+  PGTK_TRACE ("xg_create_frame_outer_widgets.");
+  block_input ();
+
+  wtop = gtk_window_new (type);
+  gtk_widget_add_events(wtop, GDK_ALL_EVENTS_MASK);
+
+  xg_set_screen (wtop, f);
+
+  wvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  whbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_box_set_homogeneous (GTK_BOX (wvbox), FALSE);
+  gtk_box_set_homogeneous (GTK_BOX (whbox), FALSE);
+
+  /* Use same names as the Xt port does.  I.e. Emacs.pane.emacs by default */
+  gtk_widget_set_name (wtop, EMACS_CLASS);
+  gtk_widget_set_name (wvbox, "pane");
+
+  /* If this frame has a title or name, set it in the title bar.  */
+  if (! NILP (f->title))
+    title = SSDATA (ENCODE_UTF_8 (f->title));
+  else if (! NILP (f->name))
+    title = SSDATA (ENCODE_UTF_8 (f->name));
+
+  if (title)
+    gtk_window_set_title (GTK_WINDOW (wtop), title);
+
+  if (FRAME_UNDECORATED (f))
+    {
+      gtk_window_set_decorated (GTK_WINDOW (wtop), FALSE);
+      store_frame_param (f, Qundecorated, Qt);
+    }
+
+  FRAME_GTK_OUTER_WIDGET (f) = wtop;
+  f->output_data.xp->vbox_widget = wvbox;
+  f->output_data.xp->hbox_widget = whbox;
+
+  gtk_container_add (GTK_CONTAINER (wtop), wvbox);
+  gtk_box_pack_start (GTK_BOX (wvbox), whbox, TRUE, TRUE, 0);
+
+  if (FRAME_EXTERNAL_TOOL_BAR (f))
+    update_frame_tool_bar (f);
+
+#if ! GTK_CHECK_VERSION (3, 22, 0)
+  gtk_window_set_wmclass (GTK_WINDOW (wtop),
+                          SSDATA (Vx_resource_name),
+                          SSDATA (Vx_resource_class));
+#endif
+
+  /* Convert our geometry parameters into a geometry string
+     and specify it.
+     GTK will itself handle calculating the real position this way.  */
+  xg_set_geometry (f);
+  f->win_gravity
+    = gtk_window_get_gravity (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
+
+  gtk_window_set_resizable (GTK_WINDOW (wtop), TRUE);
+
+  if (FRAME_OVERRIDE_REDIRECT (f))
+    {
+      GdkWindow *gwin = gtk_widget_get_window (wtop);
+
+      if (gwin)
+       gdk_window_set_override_redirect (gwin, TRUE);
+    }
+
+  /* Steal a tool tip window we can move ourselves.  */
+  f->output_data.xp->ttip_widget = 0;
+  f->output_data.xp->ttip_lbl = 0;
+  f->output_data.xp->ttip_window = 0;
+  gtk_widget_set_tooltip_text (wtop, "Dummy text");
+  g_signal_connect (wtop, "query-tooltip", G_CALLBACK (qttip_cb), f);
+
+  {
+    GdkScreen *screen = gtk_widget_get_screen (wtop);
+    GtkSettings *gs = gtk_settings_get_for_screen (screen);
+    /* Only connect this signal once per screen.  */
+    if (! g_signal_handler_find (G_OBJECT (gs),
+                                 G_SIGNAL_MATCH_FUNC,
+                                 0, 0, 0,
+                                 (gpointer) G_CALLBACK (style_changed_cb),
+                                 0))
+      {
+        g_signal_connect (G_OBJECT (gs), "notify::gtk-theme-name",
+                          G_CALLBACK (style_changed_cb),
+                          gdk_screen_get_display (screen));
+      }
+  }
+
+  unblock_input ();
+}
+#endif
+
 void
 xg_free_frame_widgets (struct frame *f)
 {
@@ -1784,10 +1921,17 @@ void
 xg_set_skip_taskbar (struct frame *f, Lisp_Object skip_taskbar)
 {
   block_input ();
+#ifndef HAVE_PGTK
   if (FRAME_GTK_WIDGET (f))
     gdk_window_set_skip_taskbar_hint
       (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)),
        NILP (skip_taskbar) ? FALSE : TRUE);
+#else
+  if (FRAME_GTK_OUTER_WIDGET (f))
+    gdk_window_set_skip_taskbar_hint
+      (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)),
+       NILP (skip_taskbar) ? FALSE : TRUE);
+#endif
   unblock_input ();
 }
 
@@ -1812,7 +1956,13 @@ void
 xg_set_no_accept_focus (struct frame *f, Lisp_Object no_accept_focus)
 {
   block_input ();
-  if (FRAME_GTK_WIDGET (f))
+  if (
+#ifndef HAVE_PGTK
+      FRAME_GTK_WIDGET (f)
+#else
+      FRAME_GTK_OUTER_WIDGET (f)
+#endif
+      )
     {
       GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
       gboolean g_no_accept_focus = NILP (no_accept_focus) ? TRUE : FALSE;
diff --git a/src/gtkutil.h b/src/gtkutil.h
index b7f67ba..0400734 100644
--- a/src/gtkutil.h
+++ b/src/gtkutil.h
@@ -179,6 +179,9 @@ extern void xg_set_background_color (struct frame *f, 
unsigned long bg);
 extern bool xg_check_special_colors (struct frame *f,
                                     const char *color_name,
                                     Emacs_Color *color);
+#ifdef HAVE_PGTK
+extern void xg_create_frame_outer_widgets (struct frame *f);
+#endif
 
 #ifndef HAVE_PGTK
 extern void xg_set_frame_icon (struct frame *f,
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 06fb4e2..c6909ba 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -231,7 +231,7 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, 
Lisp_Object oldval)
 static void
 pgtk_set_name_internal (struct frame *f, Lisp_Object name)
 {
-  if (FRAME_GTK_WIDGET (f))
+  if (FRAME_GTK_OUTER_WIDGET (f))
     {
       block_input ();
       {
@@ -1523,18 +1523,32 @@ This function is an internal primitive--use 
`make-frame' instead.  */ )
       struct frame *p = XFRAME (parent_frame);
 
       block_input ();
+
       PGTK_TRACE ("x_set_parent_frame x: %d, y: %d", f->left_pos, f->top_pos);
-      gtk_window_set_transient_for (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
-                                   GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (p)));
-      gtk_window_set_attached_to (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
-                                 FRAME_GTK_WIDGET (p));
-      gtk_window_set_destroy_with_parent (GTK_WINDOW
-                                         (FRAME_GTK_OUTER_WIDGET (f)), TRUE);
-      gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
+      GtkWidget *fixed = FRAME_GTK_WIDGET (f);
+      GtkWidget *fixed_of_p = FRAME_GTK_WIDGET (p);
+      GtkWidget *whbox_of_f = gtk_widget_get_parent (fixed);
+      g_object_ref (fixed);
+      gtk_container_remove (GTK_CONTAINER (whbox_of_f), fixed);
+      gtk_fixed_put (GTK_FIXED (fixed_of_p), fixed, f->left_pos, f->top_pos);
+      gtk_widget_show_all (fixed);
+      g_object_unref (fixed);
+
+      gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
+      FRAME_GTK_OUTER_WIDGET (f) = NULL;
+      FRAME_OUTPUT_DATA (f)->vbox_widget = NULL;
+      FRAME_OUTPUT_DATA (f)->hbox_widget = NULL;
+      FRAME_OUTPUT_DATA (f)->menubar_widget = NULL;
+      FRAME_OUTPUT_DATA (f)->toolbar_widget = NULL;
+      FRAME_OUTPUT_DATA (f)->ttip_widget = NULL;
+      FRAME_OUTPUT_DATA (f)->ttip_lbl = NULL;
+      FRAME_OUTPUT_DATA (f)->ttip_window = NULL;
+
       unblock_input ();
     }
 
-  gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
+  if (FRAME_GTK_OUTER_WIDGET (f))
+    gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
 
   gui_default_parameter (f, parms, Qno_focus_on_map, Qnil,
                         NULL, NULL, RES_TYPE_BOOLEAN);
@@ -3298,8 +3312,15 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
 
   /* Get these here because they can't be got in configure_event(). */
   int left_pos, top_pos;
-  gtk_window_get_position (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
-                          &left_pos, &top_pos);
+  if (FRAME_GTK_OUTER_WIDGET (f)) {
+    gtk_window_get_position (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+                            &left_pos, &top_pos);
+  } else {
+    GtkAllocation alloc;
+    gtk_widget_get_allocation (FRAME_GTK_WIDGET (f), &alloc);
+    left_pos = alloc.x;
+    top_pos = alloc.y;
+  }
 
   int native_left = left_pos + border;
   int native_top = top_pos + border + title_height;
@@ -3647,6 +3668,8 @@ syms_of_pgtkfns (void)
   DEFSYM (Qframe_title_format, "frame-title-format");
   DEFSYM (Qicon_title_format, "icon-title-format");
   DEFSYM (Qdark, "dark");
+  DEFSYM (Qhide, "hide");
+  DEFSYM (Qresize_mode, "resize-mode");
 
   DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
               doc: /* A string indicating the foreground color of the cursor 
box.  */);
@@ -3799,6 +3822,28 @@ When using Gtk+ tooltips, the tooltip face is not used.  
*/);
 Value is a pair (COLUMNS . ROWS).  Text larger than this is clipped.  */);
   Vx_max_tooltip_size = Fcons (make_fixnum (80), make_fixnum (40));
 
+  DEFVAR_LISP ("x-gtk-resize-child-frames", x_gtk_resize_child_frames,
+    doc: /* If non-nil, resize child frames specially with GTK builds.
+If this is nil, resize child frames like any other frames.  This is the
+default and usually works with most desktops.  Some desktop environments
+(GNOME shell in particular when using the mutter window manager),
+however, may refuse to resize a child frame when Emacs is built with
+GTK3.  For those environments, the two settings below are provided.
+
+If this equals the symbol 'hide', Emacs temporarily hides the child
+frame during resizing.  This approach seems to work reliably, may
+however induce some flicker when the frame is made visible again.
+
+If this equals the symbol 'resize-mode', Emacs uses GTK's resize mode to
+always trigger an immediate resize of the child frame.  This method is
+deprecated by GTK and may not work in future versions of that toolkit.
+It also may freeze Emacs when used with other desktop environments.  It
+avoids, however, the unpleasant flicker induced by the hiding approach.
+
+This variable is considered a temporary workaround and will be hopefully
+eliminated in future versions of Emacs.  */);
+  x_gtk_resize_child_frames = Qnil;
+
 
   DEFSYM (Qmono, "mono");
   DEFSYM (Qassq_delete_all, "assq-delete-all");
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index 6d8b1ec..d62e2a3 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -60,6 +60,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #include "font.h"
 #include "xsettings.h"
 #include "pgtkselect.h"
+#include "emacsgtkfixed.h"
 
 #define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0)
 
@@ -227,10 +228,10 @@ x_free_frame_resources (struct frame *f)
 
   if (FRAME_X_OUTPUT (f)->border_color_css_provider != NULL)
     {
-      GtkStyleContext *ctxt =
-       gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f));
+      GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f));
       GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider;
       gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old));
+      g_object_unref (old);
       FRAME_X_OUTPUT (f)->border_color_css_provider = NULL;
     }
 
@@ -250,7 +251,7 @@ x_free_frame_resources (struct frame *f)
       FRAME_X_OUTPUT (f)->scrollbar_background_css_provider = NULL;
     }
 
-  gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
+  gtk_widget_destroy (FRAME_WIDGET (f));
 
   if (FRAME_X_OUTPUT (f)->cr_surface_visible_bell != NULL)
     {
@@ -286,6 +287,80 @@ x_destroy_window (struct frame *f)
   dpyinfo->reference_count--;
 }
 
+/* Calculate the absolute position in frame F
+   from its current recorded position values and gravity.  */
+
+static void
+x_calc_absolute_position (struct frame *f)
+{
+  int flags = f->size_hint_flags;
+  struct frame *p = FRAME_PARENT_FRAME (f);
+
+  /* We have nothing to do if the current position
+     is already for the top-left corner.  */
+  if (! ((flags & XNegative) || (flags & YNegative)))
+    return;
+
+  /* Treat negative positions as relative to the leftmost bottommost
+     position that fits on the screen.  */
+  if ((flags & XNegative) && (f->left_pos <= 0))
+    {
+      int width = FRAME_PIXEL_WIDTH (f);
+
+      /* A frame that has been visible at least once should have outer
+        edges.  */
+      if (f->output_data.pgtk->has_been_visible && !p)
+       {
+         Lisp_Object frame;
+         Lisp_Object edges = Qnil;
+
+         XSETFRAME (frame, f);
+         edges = Fpgtk_frame_edges (frame, Qouter_edges);
+         if (!NILP (edges))
+           width = (XFIXNUM (Fnth (make_fixnum (2), edges))
+                    - XFIXNUM (Fnth (make_fixnum (0), edges)));
+       }
+
+      if (p)
+       f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width
+                      + f->left_pos);
+      else
+       f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
+                      - width + f->left_pos);
+
+    }
+
+  if ((flags & YNegative) && (f->top_pos <= 0))
+    {
+      int height = FRAME_PIXEL_HEIGHT (f);
+
+      if (f->output_data.pgtk->has_been_visible && !p)
+       {
+         Lisp_Object frame;
+         Lisp_Object edges = Qnil;
+
+         XSETFRAME (frame, f);
+         if (NILP (edges))
+           edges = Fpgtk_frame_edges (frame, Qouter_edges);
+         if (!NILP (edges))
+           height = (XFIXNUM (Fnth (make_fixnum (3), edges))
+                     - XFIXNUM (Fnth (make_fixnum (1), edges)));
+       }
+
+      if (p)
+       f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width
+                      + f->top_pos);
+      else
+       f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
+                     - height + f->top_pos);
+  }
+
+  /* The left_pos and top_pos
+     are now relative to the top and left screen edges,
+     so the flags should correspond.  */
+  f->size_hint_flags &= ~ (XNegative | YNegative);
+}
+
 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
    to really change the position, and 0 when calling from
    x_make_frame_visible (in that case, XOFF and YOFF are the current
@@ -300,48 +375,60 @@ x_set_offset (struct frame *f, int xoff, int yoff, int 
change_gravity)
 {
   PGTK_TRACE ("x_set_offset: %d,%d,%d.", xoff, yoff, change_gravity);
 
-  struct frame *parent = FRAME_PARENT_FRAME (f);
-  GtkAllocation a = { 0 };
-  int surface_pos_x = 0;
-  int surface_pos_y = 0;
-
-  if (parent)
-    {
-      /* determing the "height" of the titlebar, by finding the
-        location of the "emacsfixed" widget on the surface/window */
-      GtkWidget *w = FRAME_GTK_WIDGET (parent);
-      gtk_widget_get_allocation (w, &a);
-    }
+  int modified_top, modified_left;
 
   if (change_gravity > 0)
     {
-      f->size_hint_flags &= ~(XNegative | YNegative);
-      f->left_pos = xoff;
       f->top_pos = yoff;
-
+      f->left_pos = xoff;
+      f->size_hint_flags &= ~ (XNegative | YNegative);
       if (xoff < 0)
-       {
-         f->size_hint_flags |= XNegative;
-       }
+       f->size_hint_flags |= XNegative;
       if (yoff < 0)
-       {
-         f->size_hint_flags |= YNegative;
-       }
+       f->size_hint_flags |= YNegative;
       f->win_gravity = NorthWestGravity;
     }
 
+  x_calc_absolute_position (f);
+
   block_input ();
-  surface_pos_y = f->top_pos + a.y;
-  surface_pos_x = f->left_pos + a.x;
+  x_wm_set_size_hint (f, 0, false);
 
-  /* When a position change was requested and the outer GTK widget
-     has been realized already, leave it to gtk_window_move to DTRT
-     and return.  Used for Bug#25851 and Bug#25943.  */
-  if (change_gravity != 0 && FRAME_GTK_OUTER_WIDGET (f))
+  if (x_gtk_use_window_move)
+    {
+      if (change_gravity != 0)
+       {
+         if (FRAME_GTK_OUTER_WIDGET (f))
+           {
+             gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+                              f->left_pos, f->top_pos);
+           }
+         else
+           {
+             GtkWidget *fixed = FRAME_GTK_WIDGET (f);
+             GtkWidget *parent = gtk_widget_get_parent (fixed);
+             gtk_fixed_move (GTK_FIXED (parent), fixed,
+                             f->left_pos, f->top_pos);
+           }
+       }
+      unblock_input ();
+      return;
+    }
+
+  modified_left = f->left_pos;
+  modified_top = f->top_pos;
+
+  if (FRAME_GTK_OUTER_WIDGET (f))
     {
-      PGTK_TRACE ("x_set_offset: move to %d,%d.", surface_pos_x, 
surface_pos_y);
       gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
-                      surface_pos_x, surface_pos_y);
+                      modified_left, modified_top);
+    }
+  else
+    {
+      GtkWidget *fixed = FRAME_GTK_WIDGET (f);
+      GtkWidget *parent = gtk_widget_get_parent (fixed);
+      gtk_fixed_move (GTK_FIXED (parent), fixed,
+                     modified_left, modified_top);
     }
 
   unblock_input ();
@@ -397,7 +484,7 @@ pgtk_set_window_size (struct frame *f,
   x_wm_set_size_hint (f, 0, 0);
   xg_frame_set_char_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth),
                          FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight));
-  gtk_widget_queue_resize (FRAME_GTK_OUTER_WIDGET (f));
+  gtk_widget_queue_resize (FRAME_WIDGET (f));
 
   unblock_input ();
 }
@@ -488,8 +575,9 @@ pgtk_make_frame_visible (struct frame *f)
 
   if (!FRAME_VISIBLE_P (f))
     {
-      gtk_widget_show (win);
-      gtk_window_deiconify (GTK_WINDOW (win));
+      gtk_widget_show (FRAME_WIDGET (f));
+      if (win)
+       gtk_window_deiconify (GTK_WINDOW (win));
 
       if (FLOATP (Vpgtk_wait_for_event_timeout))
        {
@@ -498,7 +586,7 @@ pgtk_make_frame_visible (struct frame *f)
          int found = 0;
          int timed_out = 0;
          gulong id =
-           g_signal_connect (win, "map-event",
+           g_signal_connect (FRAME_WIDGET (f), "map-event",
                              G_CALLBACK
                              (pgtk_make_frame_visible_wait_for_map_event_cb),
                              &found);
@@ -508,7 +596,7 @@ pgtk_make_frame_visible (struct frame *f)
                           &timed_out);
          while (!found && !timed_out)
            gtk_main_iteration ();
-         g_signal_handler_disconnect (win, id);
+         g_signal_handler_disconnect (FRAME_WIDGET (f), id);
          if (!timed_out)
            g_source_remove (src);
        }
@@ -524,9 +612,7 @@ pgtk_make_frame_invisible (struct frame *f)
 {
   PGTK_TRACE ("pgtk_make_frame_invisible");
 
-  GtkWidget *win = FRAME_OUTPUT_DATA (f)->widget;
-
-  gtk_widget_hide (win);
+  gtk_widget_hide (FRAME_WIDGET (f));
 
   SET_FRAME_VISIBLE (f, 0);
   SET_FRAME_ICONIFIED (f, false);
@@ -668,25 +754,89 @@ x_set_parent_frame (struct frame *f, Lisp_Object 
new_value,
    -------------------------------------------------------------------------- 
*/
 {
   struct frame *p = NULL;
-  PGTK_TRACE ("x_set_parent_frame x: %d, y: %d", f->left_pos, f->top_pos);
 
   if (!NILP (new_value)
       && (!FRAMEP (new_value)
-         || !FRAME_LIVE_P (p = XFRAME (new_value)) || !FRAME_PGTK_P (p)))
+         || !FRAME_LIVE_P (p = XFRAME (new_value))
+         || !FRAME_PGTK_P (p)))
     {
       store_frame_param (f, Qparent_frame, old_value);
       error ("Invalid specification of `parent-frame'");
     }
 
-  if (p != FRAME_PARENT_FRAME (f) && (p != NULL))
+  if (p != FRAME_PARENT_FRAME (f))
     {
       block_input ();
-      gtk_window_set_transient_for (FRAME_NATIVE_WINDOW (f),
-                                   FRAME_NATIVE_WINDOW (p));
-      gtk_window_set_attached_to (FRAME_NATIVE_WINDOW (f),
-                                 FRAME_GTK_WIDGET (p));
-      gtk_window_move (FRAME_NATIVE_WINDOW (f), f->left_pos, f->top_pos);
-      gtk_window_set_keep_above (FRAME_NATIVE_WINDOW (f), true);
+
+      if (p != NULL)
+       {
+         if (FRAME_DISPLAY_INFO (f) != FRAME_DISPLAY_INFO (p))
+           error ("Cross display reparent.");
+       }
+
+      GtkWidget *fixed = FRAME_GTK_WIDGET (f);
+
+      GtkAllocation alloc;
+      gtk_widget_get_allocation(fixed, &alloc);
+      g_object_ref (fixed);
+
+      GtkCssProvider *provider = FRAME_X_OUTPUT (f)->border_color_css_provider;
+
+      {
+       GtkWidget *whbox_of_f = gtk_widget_get_parent (fixed);
+       gtk_container_remove (GTK_CONTAINER (whbox_of_f), fixed);
+
+       GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f));
+       gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (provider));
+
+       if (FRAME_GTK_OUTER_WIDGET (f))
+         {
+           gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
+           FRAME_GTK_OUTER_WIDGET (f) = NULL;
+           FRAME_OUTPUT_DATA (f)->vbox_widget = NULL;
+           FRAME_OUTPUT_DATA (f)->hbox_widget = NULL;
+           FRAME_OUTPUT_DATA (f)->menubar_widget = NULL;
+           FRAME_OUTPUT_DATA (f)->toolbar_widget = NULL;
+           FRAME_OUTPUT_DATA (f)->ttip_widget = NULL;
+           FRAME_OUTPUT_DATA (f)->ttip_lbl = NULL;
+           FRAME_OUTPUT_DATA (f)->ttip_window = NULL;
+         }
+      }
+
+      if (p == NULL)
+       {
+         xg_create_frame_outer_widgets (f);
+         pgtk_set_event_handler (f);
+         gtk_box_pack_start (GTK_BOX (f->output_data.pgtk->hbox_widget), 
fixed, TRUE, TRUE, 0);
+         f->output_data.pgtk->preferred_width = alloc.width;
+         f->output_data.pgtk->preferred_height = alloc.height;
+         x_wm_set_size_hint (f, 0, 0);
+         xg_frame_set_char_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, alloc.width),
+                                 FRAME_PIXEL_TO_TEXT_HEIGHT (f, alloc.height));
+         gtk_widget_queue_resize (FRAME_WIDGET (f));
+         gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
+       }
+      else
+       {
+         GtkWidget *fixed_of_p = FRAME_GTK_WIDGET (p);
+         gtk_fixed_put (GTK_FIXED (fixed_of_p), fixed, f->left_pos, 
f->top_pos);
+         gtk_widget_set_size_request (fixed, alloc.width, alloc.height);
+         gtk_widget_show_all (fixed);
+       }
+
+      GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f));
+      gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (provider),
+                                     GTK_STYLE_PROVIDER_PRIORITY_USER);
+
+      g_object_unref (fixed);
+
+      if (FRAME_GTK_OUTER_WIDGET (f)) {
+       if (EQ (x_gtk_resize_child_frames, Qresize_mode))
+         gtk_container_set_resize_mode
+           (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)),
+            p ? GTK_RESIZE_IMMEDIATE : GTK_RESIZE_QUEUE);
+      }
+
       unblock_input ();
 
       fset_parent_frame (f, new_value);
@@ -748,6 +898,9 @@ x_set_z_group (struct frame *f, Lisp_Object new_value, 
Lisp_Object old_value)
   /* doesn't work on wayland. */
   PGTK_TRACE ("x_set_z_group");
 
+  if (!FRAME_GTK_OUTER_WIDGET (f))
+    return;
+
   if (NILP (new_value))
     {
       gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
@@ -2900,8 +3053,10 @@ pgtk_bitmap_icon (struct frame *f, Lisp_Object file)
 bool
 pgtk_text_icon (struct frame *f, const char *icon_name)
 {
-  gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), NULL);
-  gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), icon_name);
+  if (FRAME_GTK_OUTER_WIDGET (f)) {
+    gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), NULL);
+    gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), icon_name);
+  }
 
   return false;
 }
@@ -4392,6 +4547,9 @@ pgtk_judge_scroll_bars (struct frame *f)
 static void
 set_fullscreen_state (struct frame *f)
 {
+  if (!FRAME_GTK_OUTER_WIDGET (f))
+    return;
+
   GtkWindow *widget = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
   switch (f->want_fullscreen)
     {
@@ -4571,24 +4729,27 @@ frame_highlight (struct frame *f)
      using that same window-manager binary for ever.  Let's not crash just
      because of this (bug#9310).  */
 
+  GtkWidget *w = FRAME_WIDGET (f);
+
   char *css =
     g_strdup_printf ("decoration { border: solid %dpx #%06x; }",
                     f->border_width,
-                    (unsigned int) FRAME_X_OUTPUT (f)->
-                    border_pixel & 0x00ffffff);
-  GtkStyleContext *ctxt =
-    gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f));
+                    (unsigned int) FRAME_X_OUTPUT (f)->border_pixel & 
0x00ffffff);
+
+  GtkStyleContext *ctxt = gtk_widget_get_style_context (w);
   GtkCssProvider *css_provider = gtk_css_provider_new ();
   gtk_css_provider_load_from_data (css_provider, css, -1, NULL);
   gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (css_provider),
                                  GTK_STYLE_PROVIDER_PRIORITY_USER);
-  g_object_unref (css_provider);
   g_free (css);
 
   GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider;
   FRAME_X_OUTPUT (f)->border_color_css_provider = css_provider;
   if (old != NULL)
-    gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old));
+    {
+      gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old));
+      g_object_unref (old);
+    }
 
   unblock_input ();
   gui_update_cursor (f, true);
@@ -4605,22 +4766,26 @@ frame_unhighlight (struct frame *f)
   block_input ();
   /* Same as above for XSetWindowBorder (bug#9310).  */
 
+  GtkWidget *w = FRAME_WIDGET (f);
+
   char *css =
     g_strdup_printf ("decoration { border: dotted %dpx #ffffff; }",
                     f->border_width);
-  GtkStyleContext *ctxt =
-    gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f));
+
+  GtkStyleContext *ctxt = gtk_widget_get_style_context (w);
   GtkCssProvider *css_provider = gtk_css_provider_new ();
   gtk_css_provider_load_from_data (css_provider, css, -1, NULL);
   gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (css_provider),
                                  GTK_STYLE_PROVIDER_PRIORITY_USER);
-  g_object_unref (css_provider);
   g_free (css);
 
   GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider;
   FRAME_X_OUTPUT (f)->border_color_css_provider = css_provider;
   if (old != NULL)
-    gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old));
+    {
+      gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old));
+      g_object_unref (old);
+    }
 
   unblock_input ();
   gui_update_cursor (f, true);
@@ -4793,6 +4958,7 @@ struct pgtk_window_is_of_frame_recursive_t
 {
   GdkWindow *window;
   bool result;
+  GtkWidget *emacs_gtk_fixed;  // stop on emacsgtkfixed other than this.
 };
 
 static void
@@ -4803,15 +4969,19 @@ pgtk_window_is_of_frame_recursive (GtkWidget * widget, 
gpointer data)
   if (datap->result)
     return;
 
+  if (EMACS_IS_FIXED (widget) && widget != datap->emacs_gtk_fixed)
+    return;
+
   if (gtk_widget_get_window (widget) == datap->window)
     {
       datap->result = true;
       return;
     }
 
-  if (GTK_IS_CONTAINER (widget))
+  if (GTK_IS_CONTAINER (widget)) {
     gtk_container_foreach (GTK_CONTAINER (widget),
                           pgtk_window_is_of_frame_recursive, datap);
+  }
 }
 
 static bool
@@ -4820,7 +4990,8 @@ pgtk_window_is_of_frame (struct frame *f, GdkWindow * 
window)
   struct pgtk_window_is_of_frame_recursive_t data;
   data.window = window;
   data.result = false;
-  pgtk_window_is_of_frame_recursive (FRAME_GTK_OUTER_WIDGET (f), &data);
+  data.emacs_gtk_fixed = FRAME_GTK_WIDGET (f);
+  pgtk_window_is_of_frame_recursive (FRAME_WIDGET (f), &data);
   return data.result;
 }
 
@@ -5068,6 +5239,8 @@ pgtk_clear_under_internal_border (struct frame *f)
     }
 }
 
+#ifdef HAVE_PGTK
+
 static void
 print_widget_tree_recursive (GtkWidget * w, gpointer user_data)
 {
@@ -5108,6 +5281,8 @@ print_widget_tree (GtkWidget * w)
   print_widget_tree_recursive (w, indent);
 }
 
+#endif
+
 static gboolean
 pgtk_handle_draw (GtkWidget * widget, cairo_t * cr, gpointer * data)
 {
@@ -5115,7 +5290,9 @@ pgtk_handle_draw (GtkWidget * widget, cairo_t * cr, 
gpointer * data)
 
   PGTK_TRACE ("pgtk_handle_draw");
 
+#ifdef HAVE_PGTK
   print_widget_tree (widget);
+#endif
 
   GdkWindow *win = gtk_widget_get_window (widget);
 
@@ -6385,11 +6562,11 @@ pgtk_set_event_handler (struct frame *f)
                    NULL);
   g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "delete-event",
                    G_CALLBACK (delete_event), NULL);
-  g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "map-event",
-                   G_CALLBACK (map_event), NULL);
   g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "event",
                    G_CALLBACK (pgtk_handle_event), NULL);
 
+  g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "map-event",
+                   G_CALLBACK (map_event), NULL);
   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "size-allocate",
                    G_CALLBACK (size_allocate), NULL);
   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "key-press-event",
diff --git a/src/pgtkterm.h b/src/pgtkterm.h
index cff1633..ad66039 100644
--- a/src/pgtkterm.h
+++ b/src/pgtkterm.h
@@ -428,6 +428,9 @@ enum
 #define FRAME_FONT(f)             (FRAME_X_OUTPUT(f)->font)
 #define FRAME_GTK_OUTER_WIDGET(f) (FRAME_X_OUTPUT(f)->widget)
 #define FRAME_GTK_WIDGET(f)       (FRAME_X_OUTPUT(f)->edit_widget)
+#define FRAME_WIDGET(f)           (FRAME_GTK_OUTER_WIDGET(f) ?         \
+                                   FRAME_GTK_OUTER_WIDGET(f) :         \
+                                   FRAME_GTK_WIDGET(f))
 
 /* aliases */
 #define FRAME_PGTK_VIEW(f)         FRAME_GTK_WIDGET(f)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]