Merge branch 'master' into comment-cache
[emacs.git] / src / emacsgtkfixed.c
blob64b74ea24ce96a38257965c305f82f71e8db3ce5
1 /* A Gtk Widget that inherits GtkFixed, but can be shrunk.
2 This file is only use when compiling with Gtk+ 3.
4 Copyright (C) 2011-2017 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or (at
11 your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 #include <config.h>
23 #include "lisp.h"
24 #include "frame.h"
25 #include "xterm.h"
26 #include "xwidget.h"
27 #include "emacsgtkfixed.h"
29 /* Silence a bogus diagnostic; see GNOME bug 683906. */
30 #if GNUC_PREREQ (4, 7, 0) && ! GLIB_CHECK_VERSION (2, 35, 7)
31 # pragma GCC diagnostic push
32 # pragma GCC diagnostic ignored "-Wunused-local-typedefs"
33 #endif
35 typedef struct _EmacsFixed EmacsFixed;
36 typedef struct _EmacsFixedClass EmacsFixedClass;
38 struct _EmacsFixedPrivate
40 struct frame *f;
44 static void emacs_fixed_get_preferred_width (GtkWidget *widget,
45 gint *minimum,
46 gint *natural);
47 static void emacs_fixed_get_preferred_height (GtkWidget *widget,
48 gint *minimum,
49 gint *natural);
50 static GType emacs_fixed_get_type (void);
51 G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED)
53 static EmacsFixed *
54 EMACS_FIXED (GtkWidget *widget)
56 return G_TYPE_CHECK_INSTANCE_CAST (widget, emacs_fixed_get_type (),
57 EmacsFixed);
60 #ifdef HAVE_XWIDGETS
62 static EmacsFixedClass *
63 EMACS_FIXED_GET_CLASS (GtkWidget *widget)
65 return G_TYPE_INSTANCE_GET_CLASS (widget, emacs_fixed_get_type (),
66 EmacsFixedClass);
69 struct GtkFixedPrivateL
71 GList *children;
74 static void
75 emacs_fixed_gtk_widget_size_allocate (GtkWidget *widget,
76 GtkAllocation *allocation)
78 /* For xwidgets.
80 This basically re-implements the base class method and adds an
81 additional case for an xwidget view.
83 It would be nicer if the bse class method could be called first,
84 and the the xview modification only would remain here. It wasn't
85 possible to solve it that way yet. */
86 EmacsFixedClass *klass;
87 GtkWidgetClass *parent_class;
88 struct GtkFixedPrivateL *priv;
90 klass = EMACS_FIXED_GET_CLASS (widget);
91 parent_class = g_type_class_peek_parent (klass);
92 parent_class->size_allocate (widget, allocation);
94 priv = G_TYPE_INSTANCE_GET_PRIVATE (widget, GTK_TYPE_FIXED,
95 struct GtkFixedPrivateL);
97 gtk_widget_set_allocation (widget, allocation);
99 if (gtk_widget_get_has_window (widget))
101 if (gtk_widget_get_realized (widget))
102 gdk_window_move_resize (gtk_widget_get_window (widget),
103 allocation->x,
104 allocation->y,
105 allocation->width,
106 allocation->height);
109 for (GList *children = priv->children; children; children = children->next)
111 GtkFixedChild *child = children->data;
113 if (!gtk_widget_get_visible (child->widget))
114 continue;
116 GtkRequisition child_requisition;
117 gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
119 GtkAllocation child_allocation;
120 child_allocation.x = child->x;
121 child_allocation.y = child->y;
123 if (!gtk_widget_get_has_window (widget))
125 child_allocation.x += allocation->x;
126 child_allocation.y += allocation->y;
129 child_allocation.width = child_requisition.width;
130 child_allocation.height = child_requisition.height;
132 struct xwidget_view *xv
133 = g_object_get_data (G_OBJECT (child->widget), XG_XWIDGET_VIEW);
134 if (xv)
136 child_allocation.width = xv->clip_right;
137 child_allocation.height = xv->clip_bottom - xv->clip_top;
140 gtk_widget_size_allocate (child->widget, &child_allocation);
144 #endif /* HAVE_XWIDGETS */
146 static void
147 emacs_fixed_class_init (EmacsFixedClass *klass)
149 GtkWidgetClass *widget_class;
151 widget_class = (GtkWidgetClass*) klass;
153 widget_class->get_preferred_width = emacs_fixed_get_preferred_width;
154 widget_class->get_preferred_height = emacs_fixed_get_preferred_height;
155 #ifdef HAVE_XWIDGETS
156 widget_class->size_allocate = emacs_fixed_gtk_widget_size_allocate;
157 #endif
158 g_type_class_add_private (klass, sizeof (EmacsFixedPrivate));
161 static void
162 emacs_fixed_init (EmacsFixed *fixed)
164 fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, emacs_fixed_get_type (),
165 EmacsFixedPrivate);
166 fixed->priv->f = 0;
169 GtkWidget *
170 emacs_fixed_new (struct frame *f)
172 EmacsFixed *fixed = g_object_new (emacs_fixed_get_type (), NULL);
173 EmacsFixedPrivate *priv = fixed->priv;
174 priv->f = f;
175 return GTK_WIDGET (fixed);
178 static void
179 emacs_fixed_get_preferred_width (GtkWidget *widget,
180 gint *minimum,
181 gint *natural)
183 EmacsFixed *fixed = EMACS_FIXED (widget);
184 EmacsFixedPrivate *priv = fixed->priv;
185 int w = priv->f->output_data.x->size_hints.min_width;
186 if (minimum) *minimum = w;
187 if (natural) *natural = w;
190 static void
191 emacs_fixed_get_preferred_height (GtkWidget *widget,
192 gint *minimum,
193 gint *natural)
195 EmacsFixed *fixed = EMACS_FIXED (widget);
196 EmacsFixedPrivate *priv = fixed->priv;
197 int h = priv->f->output_data.x->size_hints.min_height;
198 if (minimum) *minimum = h;
199 if (natural) *natural = h;
203 /* Override the X function so we can intercept Gtk+ 3 calls.
204 Use our values for min_width/height so that KDE don't freak out
205 (Bug#8919), and so users can resize our frames as they wish. */
207 void
208 XSetWMSizeHints (Display* d,
209 Window w,
210 XSizeHints* hints,
211 Atom prop)
213 struct x_display_info *dpyinfo = x_display_info_for_display (d);
214 struct frame *f = x_top_window_to_frame (dpyinfo, w);
215 long data[18];
216 data[0] = hints->flags;
217 data[1] = hints->x;
218 data[2] = hints->y;
219 data[3] = hints->width;
220 data[4] = hints->height;
221 data[5] = hints->min_width;
222 data[6] = hints->min_height;
223 data[7] = hints->max_width;
224 data[8] = hints->max_height;
225 data[9] = hints->width_inc;
226 data[10] = hints->height_inc;
227 data[11] = hints->min_aspect.x;
228 data[12] = hints->min_aspect.y;
229 data[13] = hints->max_aspect.x;
230 data[14] = hints->max_aspect.y;
231 data[15] = hints->base_width;
232 data[16] = hints->base_height;
233 data[17] = hints->win_gravity;
235 if ((hints->flags & PMinSize) && f)
237 int w = f->output_data.x->size_hints.min_width;
238 int h = f->output_data.x->size_hints.min_height;
239 data[5] = w;
240 data[6] = h;
243 XChangeProperty (d, w, prop, XA_WM_SIZE_HINTS, 32, PropModeReplace,
244 (unsigned char *) data, 18);
247 /* Override this X11 function.
248 This function is in the same X11 file as the one above. So we must
249 provide it also. */
251 void
252 XSetWMNormalHints (Display *d, Window w, XSizeHints *hints)
254 XSetWMSizeHints (d, w, hints, XA_WM_NORMAL_HINTS);