]> code.delx.au - gnu-emacs/blob - src/emacsgtkfixed.c
Don’t export C symbols not used elsewhere
[gnu-emacs] / src / emacsgtkfixed.c
1 /* A Gtk Widget that inherits GtkFixed, but can be shrunk.
2 This file is only use when compiling with Gtk+ 3.
3
4 Copyright (C) 2011-2016 Free Software Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
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
11 (at your option) any later version.
12
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.
17
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/>. */
20
21 #include <config.h>
22
23 #include "lisp.h"
24 #include "frame.h"
25 #include "xterm.h"
26 #ifdef HAVE_XWIDGETS
27 # include "xwidget.h"
28 #endif
29 #include "emacsgtkfixed.h"
30
31 /* Silence a bogus diagnostic; see GNOME bug 683906. */
32 #if 4 < __GNUC__ + (7 <= __GNUC_MINOR__)
33 # pragma GCC diagnostic push
34 # pragma GCC diagnostic ignored "-Wunused-local-typedefs"
35 #endif
36
37 typedef struct _EmacsFixed EmacsFixed;
38 typedef struct _EmacsFixedPrivate EmacsFixedPrivate;
39 typedef struct _EmacsFixedClass EmacsFixedClass;
40
41 struct _EmacsFixedPrivate
42 {
43 struct frame *f;
44 };
45
46
47 static void emacs_fixed_get_preferred_width (GtkWidget *widget,
48 gint *minimum,
49 gint *natural);
50 static void emacs_fixed_get_preferred_height (GtkWidget *widget,
51 gint *minimum,
52 gint *natural);
53
54 static GType emacs_fixed_get_type (void);
55 G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED)
56
57 static EmacsFixed *
58 EMACS_FIXED (GtkWidget *widget)
59 {
60 return G_TYPE_CHECK_INSTANCE_CAST (widget, emacs_fixed_get_type (),
61 EmacsFixed);
62 }
63
64 #ifdef HAVE_XWIDGETS
65
66 static EmacsFixedClass *
67 EMACS_FIXED_GET_CLASS (GtkWidget *widget)
68 {
69 return G_TYPE_INSTANCE_GET_CLASS (widget, emacs_fixed_get_type (),
70 EmacsFixedClass);
71 }
72
73 struct GtkFixedPrivateL
74 {
75 GList *children;
76 };
77
78 static void emacs_fixed_gtk_widget_size_allocate (GtkWidget *widget,
79 GtkAllocation *allocation)
80 {
81 // For xwidgets.
82
83 // This basically re-implements the base class method and adds an
84 // additional case for an xwidget view.
85
86 // It would be nicer if the bse class method could be called first,
87 // and the the xview modification only would remain here. It wasn't
88 // possible to solve it that way yet.
89 EmacsFixedClass *klass;
90 GtkWidgetClass *parent_class;
91 struct GtkFixedPrivateL* priv;
92
93 klass = EMACS_FIXED_GET_CLASS (widget);
94 parent_class = g_type_class_peek_parent (klass);
95 parent_class->size_allocate (widget, allocation);
96
97 priv = G_TYPE_INSTANCE_GET_PRIVATE (widget,
98 GTK_TYPE_FIXED,
99 struct GtkFixedPrivateL);
100
101 gtk_widget_set_allocation (widget, allocation);
102
103 if (gtk_widget_get_has_window (widget))
104 {
105 if (gtk_widget_get_realized (widget))
106 gdk_window_move_resize (gtk_widget_get_window (widget),
107 allocation->x,
108 allocation->y,
109 allocation->width,
110 allocation->height);
111 }
112
113 for (GList *children = priv->children; children; children = children->next)
114 {
115 GtkFixedChild *child = children->data;
116
117 if (!gtk_widget_get_visible (child->widget))
118 continue;
119
120 GtkRequisition child_requisition;
121 gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
122
123 GtkAllocation child_allocation;
124 child_allocation.x = child->x;
125 child_allocation.y = child->y;
126
127 if (!gtk_widget_get_has_window (widget))
128 {
129 child_allocation.x += allocation->x;
130 child_allocation.y += allocation->y;
131 }
132
133 child_allocation.width = child_requisition.width;
134 child_allocation.height = child_requisition.height;
135
136 struct xwidget_view *xv
137 = g_object_get_data (G_OBJECT (child->widget), XG_XWIDGET_VIEW);
138 if (xv)
139 {
140 child_allocation.width = xv->clip_right;
141 child_allocation.height = xv->clip_bottom - xv->clip_top;
142 }
143
144 gtk_widget_size_allocate (child->widget, &child_allocation);
145 }
146 }
147
148 #endif /* HAVE_XWIDGETS */
149
150 static void
151 emacs_fixed_class_init (EmacsFixedClass *klass)
152 {
153 GtkWidgetClass *widget_class;
154
155 widget_class = (GtkWidgetClass*) klass;
156
157
158 widget_class->get_preferred_width = emacs_fixed_get_preferred_width;
159 widget_class->get_preferred_height = emacs_fixed_get_preferred_height;
160 #ifdef HAVE_XWIDGETS
161 widget_class->size_allocate = emacs_fixed_gtk_widget_size_allocate;
162 #endif
163 g_type_class_add_private (klass, sizeof (EmacsFixedPrivate));
164 }
165
166
167 static void
168 emacs_fixed_init (EmacsFixed *fixed)
169 {
170 fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, emacs_fixed_get_type (),
171 EmacsFixedPrivate);
172 fixed->priv->f = 0;
173 }
174
175 /**
176 * emacs_fixed_new:
177 *
178 * Creates a new #EmacsFixed.
179 *
180 * Returns: a new #EmacsFixed.
181 */
182 GtkWidget*
183 emacs_fixed_new (struct frame *f)
184 {
185 EmacsFixed *fixed = g_object_new (emacs_fixed_get_type (), NULL);
186 EmacsFixedPrivate *priv = fixed->priv;
187 priv->f = f;
188 return GTK_WIDGET (fixed);
189 }
190
191 static void
192 emacs_fixed_get_preferred_width (GtkWidget *widget,
193 gint *minimum,
194 gint *natural)
195 {
196 EmacsFixed *fixed = EMACS_FIXED (widget);
197 EmacsFixedPrivate *priv = fixed->priv;
198 int w = priv->f->output_data.x->size_hints.min_width;
199 if (minimum) *minimum = w;
200 if (natural) *natural = w;
201 }
202
203 static void
204 emacs_fixed_get_preferred_height (GtkWidget *widget,
205 gint *minimum,
206 gint *natural)
207 {
208 EmacsFixed *fixed = EMACS_FIXED (widget);
209 EmacsFixedPrivate *priv = fixed->priv;
210 int h = priv->f->output_data.x->size_hints.min_height;
211 if (minimum) *minimum = h;
212 if (natural) *natural = h;
213 }
214
215
216 /* Override the X function so we can intercept Gtk+ 3 calls.
217 Use our values for min_width/height so that KDE don't freak out
218 (Bug#8919), and so users can resize our frames as they wish. */
219
220 void
221 XSetWMSizeHints (Display* d,
222 Window w,
223 XSizeHints* hints,
224 Atom prop)
225 {
226 struct x_display_info *dpyinfo = x_display_info_for_display (d);
227 struct frame *f = x_top_window_to_frame (dpyinfo, w);
228 long data[18];
229 data[0] = hints->flags;
230 data[1] = hints->x;
231 data[2] = hints->y;
232 data[3] = hints->width;
233 data[4] = hints->height;
234 data[5] = hints->min_width;
235 data[6] = hints->min_height;
236 data[7] = hints->max_width;
237 data[8] = hints->max_height;
238 data[9] = hints->width_inc;
239 data[10] = hints->height_inc;
240 data[11] = hints->min_aspect.x;
241 data[12] = hints->min_aspect.y;
242 data[13] = hints->max_aspect.x;
243 data[14] = hints->max_aspect.y;
244 data[15] = hints->base_width;
245 data[16] = hints->base_height;
246 data[17] = hints->win_gravity;
247
248 if ((hints->flags & PMinSize) && f)
249 {
250 int w = f->output_data.x->size_hints.min_width;
251 int h = f->output_data.x->size_hints.min_height;
252 data[5] = w;
253 data[6] = h;
254 }
255
256 XChangeProperty (d, w, prop, XA_WM_SIZE_HINTS, 32, PropModeReplace,
257 (unsigned char *) data, 18);
258 }
259
260 /* Override this X11 function.
261 This function is in the same X11 file as the one above. So we must
262 provide it also. */
263
264 void
265 XSetWMNormalHints (Display *d, Window w, XSizeHints *hints)
266 {
267 XSetWMSizeHints (d, w, hints, XA_WM_NORMAL_HINTS);
268 }