aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Rudalics2020-04-06 09:22:36 +0200
committerMartin Rudalics2020-04-06 09:22:36 +0200
commitc49d379f17bcb0ce82604def2eaa04bda00bd5ec (patch)
treee33f6534413fb16a198739c0ca3f160a28a5edd3 /src
parent6de20c7eab0dd8360e78d744dbf62aecc7f78281 (diff)
downloademacs-c49d379f17bcb0ce82604def2eaa04bda00bd5ec.tar.gz
emacs-c49d379f17bcb0ce82604def2eaa04bda00bd5ec.zip
Fix some problems with moving and resizing child frames
(1) Provide new option 'x-gtk-resize-child-frames' which allows to either hide a child frame during resizing or asks GTK to resize it "immediately". This is needed because desktops like GNOME shell otherwise won't allow resizing child frames at all. (2) Do not try to synchronize the position of a child frame after moving it. Needed because the present implementation introduces a 0.5 secs delay which makes dragging child frames virtually impossible with Lucid and Motif toolkits on desktops like GNOME shell that use invisible outer frame borders. For further information see the thread starting with https://lists.gnu.org/archive/html/emacs-devel/2020-01/msg00343.html * src/frame.c (syms_of_frame): New symbol Qxg_frame_set_char_size_4. * src/gtkutil.c (xg_frame_set_char_size): Hide child frame during resizing when 'x-gtk-resize-child-frames' equals 'hide'. * src/xfns.c (x_set_parent_frame, Fx_create_frame): Set gtk_container_resize_mode to GTK_RESIZE_IMMEDIATE for child frames when'x-gtk-resize-child-frames' equals 'resize-mode'. (Fx_gtk_debug): New function to toggle interactive GTK debugging from within Emacs. (syms_of_xfns): New symbols Qhide and Qresize_mode. (x-gtk-resize-child-frames): New option that allows to resize child frames on desktops like GNOME shell (with the mutter WM) that otherwise refuse to resize them. * src/xterm.c (x_set_offset): Don't x_sync_with_move for child frames, it makes moving child frames virtually impossible with the Lucid and Motif toolkits.
Diffstat (limited to 'src')
-rw-r--r--src/frame.c1
-rw-r--r--src/gtkutil.c33
-rw-r--r--src/xfns.c56
-rw-r--r--src/xterm.c43
4 files changed, 108 insertions, 25 deletions
diff --git a/src/frame.c b/src/frame.c
index ecf175f4f99..4dd8bb18041 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -5943,6 +5943,7 @@ syms_of_frame (void)
5943 DEFSYM (Qxg_frame_set_char_size_1, "xg-frame-set-char-size-1"); 5943 DEFSYM (Qxg_frame_set_char_size_1, "xg-frame-set-char-size-1");
5944 DEFSYM (Qxg_frame_set_char_size_2, "xg-frame-set-char-size-2"); 5944 DEFSYM (Qxg_frame_set_char_size_2, "xg-frame-set-char-size-2");
5945 DEFSYM (Qxg_frame_set_char_size_3, "xg-frame-set-char-size-3"); 5945 DEFSYM (Qxg_frame_set_char_size_3, "xg-frame-set-char-size-3");
5946 DEFSYM (Qxg_frame_set_char_size_4, "xg-frame-set-char-size-4");
5946 DEFSYM (Qx_set_window_size_1, "x-set-window-size-1"); 5947 DEFSYM (Qx_set_window_size_1, "x-set-window-size-1");
5947 DEFSYM (Qx_set_window_size_2, "x-set-window-size-2"); 5948 DEFSYM (Qx_set_window_size_2, "x-set-window-size-2");
5948 DEFSYM (Qx_set_window_size_3, "x-set-window-size-3"); 5949 DEFSYM (Qx_set_window_size_3, "x-set-window-size-3");
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 5e7cf3d2114..e374bdbe037 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -941,9 +941,8 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight)
941 } 941 }
942} 942}
943 943
944/* Resize the outer window of frame F after changing the height. 944/** Resize the outer window of frame F. WIDTH and HEIGHT are the new
945 COLUMNS/ROWS is the size the edit area shall have after the resize. */ 945 pixel sizes of F's text area. */
946
947void 946void
948xg_frame_set_char_size (struct frame *f, int width, int height) 947xg_frame_set_char_size (struct frame *f, int width, int height)
949{ 948{
@@ -954,6 +953,7 @@ xg_frame_set_char_size (struct frame *f, int width, int height)
954 int totalheight 953 int totalheight
955 = pixelheight + FRAME_TOOLBAR_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f); 954 = pixelheight + FRAME_TOOLBAR_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f);
956 int totalwidth = pixelwidth + FRAME_TOOLBAR_WIDTH (f); 955 int totalwidth = pixelwidth + FRAME_TOOLBAR_WIDTH (f);
956 bool was_visible = false;
957 957
958 if (FRAME_PIXEL_HEIGHT (f) == 0) 958 if (FRAME_PIXEL_HEIGHT (f) == 0)
959 return; 959 return;
@@ -996,12 +996,35 @@ xg_frame_set_char_size (struct frame *f, int width, int height)
996 gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), 996 gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
997 totalwidth, gheight); 997 totalwidth, gheight);
998 } 998 }
999 else if (FRAME_PARENT_FRAME (f) && FRAME_VISIBLE_P (f)
1000 && EQ (x_gtk_resize_child_frames, Qhide))
1001 {
1002 was_visible = true;
1003
1004 if (totalwidth != gwidth || totalheight != gheight)
1005 {
1006 frame_size_history_add
1007 (f, Qxg_frame_set_char_size_4, width, height,
1008 list2i (totalwidth, totalheight));
1009 block_input ();
1010 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
1011 unblock_input ();
1012
1013 gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1014 totalwidth, totalheight);
1015
1016 block_input ();
1017 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
1018 unblock_input ();
1019
1020 fullscreen = Qnil;
1021 }
1022 }
999 else 1023 else
1000 { 1024 {
1001 frame_size_history_add 1025 frame_size_history_add
1002 (f, Qxg_frame_set_char_size_3, width, height, 1026 (f, Qxg_frame_set_char_size_3, width, height,
1003 list2i (totalwidth, totalheight)); 1027 list2i (totalwidth, totalheight));
1004
1005 gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), 1028 gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1006 totalwidth, totalheight); 1029 totalwidth, totalheight);
1007 fullscreen = Qnil; 1030 fullscreen = Qnil;
@@ -1017,7 +1040,7 @@ xg_frame_set_char_size (struct frame *f, int width, int height)
1017 size as fast as possible. 1040 size as fast as possible.
1018 For unmapped windows, we can set rows/cols. When 1041 For unmapped windows, we can set rows/cols. When
1019 the frame is mapped again we will (hopefully) get the correct size. */ 1042 the frame is mapped again we will (hopefully) get the correct size. */
1020 if (FRAME_VISIBLE_P (f)) 1043 if (FRAME_VISIBLE_P (f) && !was_visible)
1021 { 1044 {
1022 /* Must call this to flush out events */ 1045 /* Must call this to flush out events */
1023 (void)gtk_events_pending (); 1046 (void)gtk_events_pending ();
diff --git a/src/xfns.c b/src/xfns.c
index afe1ceef81a..0fc553012bd 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -861,6 +861,12 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu
861 (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 861 (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
862 p ? FRAME_X_WINDOW (p) : DefaultRootWindow (FRAME_X_DISPLAY (f)), 862 p ? FRAME_X_WINDOW (p) : DefaultRootWindow (FRAME_X_DISPLAY (f)),
863 f->left_pos, f->top_pos); 863 f->left_pos, f->top_pos);
864#ifdef USE_GTK
865 if (EQ (x_gtk_resize_child_frames, Qresize_mode))
866 gtk_container_set_resize_mode
867 (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)),
868 p ? GTK_RESIZE_IMMEDIATE : GTK_RESIZE_QUEUE);
869#endif
864 unblock_input (); 870 unblock_input ();
865 871
866 fset_parent_frame (f, new_value); 872 fset_parent_frame (f, new_value);
@@ -4084,6 +4090,11 @@ This function is an internal primitive--use `make-frame' instead. */)
4084 block_input (); 4090 block_input ();
4085 XReparentWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 4091 XReparentWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
4086 FRAME_X_WINDOW (p), f->left_pos, f->top_pos); 4092 FRAME_X_WINDOW (p), f->left_pos, f->top_pos);
4093#ifdef USE_GTK
4094 if (EQ (x_gtk_resize_child_frames, Qresize_mode))
4095 gtk_container_set_resize_mode
4096 (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)), GTK_RESIZE_IMMEDIATE);
4097#endif
4087 unblock_input (); 4098 unblock_input ();
4088 } 4099 }
4089 4100
@@ -7742,6 +7753,22 @@ Note: Text drawn with the `x' font backend is shown with hollow boxes. */)
7742#endif /* USE_GTK */ 7753#endif /* USE_GTK */
7743#endif /* USE_CAIRO */ 7754#endif /* USE_CAIRO */
7744 7755
7756#ifdef USE_GTK
7757#ifdef HAVE_GTK3
7758DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
7759 doc: /* Toggle interactive GTK debugging. */)
7760 (Lisp_Object enable)
7761{
7762 gboolean enable_debug = !NILP (enable);
7763
7764 block_input ();
7765 gtk_window_set_interactive_debugging (enable_debug);
7766 unblock_input ();
7767
7768 return NILP (enable) ? Qnil : Qt;
7769}
7770#endif /* HAVE_GTK3 */
7771#endif /* USE_GTK */
7745 7772
7746/*********************************************************************** 7773/***********************************************************************
7747 Initialization 7774 Initialization
@@ -7810,6 +7837,8 @@ syms_of_xfns (void)
7810 DEFSYM (Qfont_parameter, "font-parameter"); 7837 DEFSYM (Qfont_parameter, "font-parameter");
7811 DEFSYM (Qmono, "mono"); 7838 DEFSYM (Qmono, "mono");
7812 DEFSYM (Qassq_delete_all, "assq-delete-all"); 7839 DEFSYM (Qassq_delete_all, "assq-delete-all");
7840 DEFSYM (Qhide, "hide");
7841 DEFSYM (Qresize_mode, "resize-mode");
7813 7842
7814#ifdef USE_CAIRO 7843#ifdef USE_CAIRO
7815 DEFSYM (Qpdf, "pdf"); 7844 DEFSYM (Qpdf, "pdf");
@@ -7986,6 +8015,28 @@ Otherwise use Emacs own tooltip implementation.
7986When using Gtk+ tooltips, the tooltip face is not used. */); 8015When using Gtk+ tooltips, the tooltip face is not used. */);
7987 x_gtk_use_system_tooltips = true; 8016 x_gtk_use_system_tooltips = true;
7988 8017
8018 DEFVAR_LISP ("x-gtk-resize-child-frames", x_gtk_resize_child_frames,
8019 doc: /* If non-nil, resize child frames specially with GTK builds.
8020If this is nil, resize child frames like any other frames. This is the
8021default and usually works with most desktops. Some desktop environments
8022(GNOME shell in particular when using the mutter window manager),
8023however, may refuse to resize a child frame when Emacs is built with
8024GTK3. For those environments, the two settings below are provided.
8025
8026If this equals the symbol 'hide', Emacs temporarily hides the child
8027frame during resizing. This approach seems to work reliably, may
8028however induce some flicker when the frame is made visible again.
8029
8030If this equals the symbol 'resize-mode', Emacs uses GTK's resize mode to
8031always trigger an immediate resize of the child frame. This method is
8032deprecated by GTK and may not work in future versions of that toolkit.
8033It also may freeze Emacs when used with other desktop environments. It
8034avoids, however, the unpleasent flicker induced by the hiding approach.
8035
8036This variable is considered a temporary workaround and will be hopefully
8037eliminated in future versions of Emacs. */);
8038 x_gtk_resize_child_frames = Qnil;
8039
7989 /* Tell Emacs about this window system. */ 8040 /* Tell Emacs about this window system. */
7990 Fprovide (Qx, Qnil); 8041 Fprovide (Qx, Qnil);
7991 8042
@@ -8101,4 +8152,9 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
8101 defsubr (&Sx_print_frames_dialog); 8152 defsubr (&Sx_print_frames_dialog);
8102#endif 8153#endif
8103#endif 8154#endif
8155#ifdef USE_GTK
8156#ifdef HAVE_GTK3
8157 defsubr (&Sx_gtk_debug);
8158#endif
8159#endif
8104} 8160}
diff --git a/src/xterm.c b/src/xterm.c
index bda976fcbbd..44396955ed0 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -10608,26 +10608,29 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
10608 modified_left, modified_top); 10608 modified_left, modified_top);
10609#endif 10609#endif
10610 10610
10611 x_sync_with_move (f, f->left_pos, f->top_pos, 10611 /* 'x_sync_with_move' is too costly for dragging child frames. */
10612 FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN); 10612 if (!FRAME_PARENT_FRAME (f))
10613 10613 {
10614 /* change_gravity is non-zero when this function is called from Lisp to 10614 x_sync_with_move (f, f->left_pos, f->top_pos,
10615 programmatically move a frame. In that case, we call 10615 FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
10616 x_check_expected_move to discover if we have a "Type A" or "Type B" 10616
10617 window manager, and, for a "Type A" window manager, adjust the position 10617 /* change_gravity is non-zero when this function is called from Lisp to
10618 of the frame. 10618 programmatically move a frame. In that case, we call
10619 10619 x_check_expected_move to discover if we have a "Type A" or "Type B"
10620 We call x_check_expected_move if a programmatic move occurred, and 10620 window manager, and, for a "Type A" window manager, adjust the position
10621 either the window manager type (A/B) is unknown or it is Type A but we 10621 of the frame.
10622 need to compute the top/left offset adjustment for this frame. */ 10622
10623 10623 We call x_check_expected_move if a programmatic move occurred, and
10624 if (change_gravity != 0 10624 either the window manager type (A/B) is unknown or it is Type A but we
10625 && !FRAME_PARENT_FRAME (f) 10625 need to compute the top/left offset adjustment for this frame. */
10626 && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN 10626
10627 || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A 10627 if (change_gravity != 0
10628 && (FRAME_X_OUTPUT (f)->move_offset_left == 0 10628 && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
10629 && FRAME_X_OUTPUT (f)->move_offset_top == 0)))) 10629 || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
10630 x_check_expected_move (f, modified_left, modified_top); 10630 && (FRAME_X_OUTPUT (f)->move_offset_left == 0
10631 && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
10632 x_check_expected_move (f, modified_left, modified_top);
10633 }
10631 10634
10632 unblock_input (); 10635 unblock_input ();
10633} 10636}