]> code.delx.au - gnu-emacs/blob - src/emacsgtkfixed.c
merge from trunk
[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-2013 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 "emacsgtkfixed.h"
24 #include <stdio.h>
25
26 #include "lisp.h"
27 #include "frame.h"
28 #include "xterm.h"
29 #ifdef HAVE_XWIDGETS
30 #include "xwidget.h"
31 #endif
32 /* Silence a bogus diagnostic; see GNOME bug 683906. */
33 #if 4 < __GNUC__ + (7 <= __GNUC_MINOR__)
34 # pragma GCC diagnostic push
35 # pragma GCC diagnostic ignored "-Wunused-local-typedefs"
36 #endif
37
38 //#define EMACS_TYPE_FIXED emacs_fixed_get_type ()
39 /* #define EMACS_FIXED(obj) \ */
40 /* G_TYPE_CHECK_INSTANCE_CAST (obj, EMACS_TYPE_FIXED, EmacsFixed) */
41
42 typedef struct _EmacsFixed EmacsFixed;
43 typedef struct _EmacsFixedPrivate EmacsFixedPrivate;
44 typedef struct _EmacsFixedClass EmacsFixedClass;
45
46 /* struct _EmacsFixed */
47 /* { */
48 /* GtkFixed container; */
49
50 /* /\*< private >*\/ */
51 /* EmacsFixedPrivate *priv; */
52 /* }; */
53
54 /* struct _EmacsFixedClass */
55 /* { */
56 /* GtkFixedClass parent_class; */
57 /* }; */
58
59 struct _EmacsFixedPrivate
60 {
61 struct frame *f;
62 };
63
64
65 static void emacs_fixed_get_preferred_width (GtkWidget *widget,
66 gint *minimum,
67 gint *natural);
68 static void emacs_fixed_get_preferred_height (GtkWidget *widget,
69 gint *minimum,
70 gint *natural);
71 G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED)
72
73 #ifdef HAVE_XWIDGETS
74 /* void aloc_callback(GtkWidget* child, GtkWidget* fixed){ */
75 /* GtkAllocation child_allocation; */
76 /* GtkRequisition child_requisition; */
77
78 /* //TODO */
79 /* // if child is an xwidget, find its clipping area and modify allocation */
80
81 /* struct xwidget_view* xv = (struct xwidget_view*) g_object_get_data (G_OBJECT (child), XG_XWIDGET_VIEW); */
82 /* printf("aloc callback %d %s\n", xv, gtk_widget_get_name(child)); */
83 /* if(xv){ */
84 /* printf(" allocation modification for xw\n"); */
85 /* gtk_widget_get_allocation(child, &child_allocation); */
86 /* child_allocation.width = xv->clip_right; */
87 /* child_allocation.height = xv->clip_bottom - xv->clip_top; */
88 /* gtk_widget_size_allocate (child, &child_allocation); */
89 /* //TODO find a way to remove this feeble workaround */
90 /* } */
91
92 /* } */
93
94 struct GtkFixedPrivateL
95 {
96 GList *children;
97 };
98
99 static void emacs_fixed_gtk_widget_size_allocate (GtkWidget *widget,
100 GtkAllocation *allocation){
101 //for xwidgets
102
103
104 //TODO 1st call base class method
105 EmacsFixedClass *klass;
106 GtkWidgetClass *parent_class;
107 struct GtkFixedPrivateL* priv;
108 GtkFixedChild *child;
109 GtkAllocation child_allocation;
110 GtkRequisition child_requisition;
111 GList *children;
112 struct xwidget_view* xv;
113
114 // printf(" emacs_fixed_gtk_widget_size_allocate\n");
115 klass = EMACS_FIXED_GET_CLASS (widget);
116 parent_class = g_type_class_peek_parent (klass);
117 parent_class->size_allocate (widget, allocation);
118
119 priv = G_TYPE_INSTANCE_GET_PRIVATE (widget,
120 GTK_TYPE_FIXED,
121 struct GtkFixedPrivateL);
122 //fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, GTK_TYPE_FIXED, GtkFixedPrivate);
123 //then modify allocations
124 /* gtk_container_foreach (widget, */
125 /* aloc_callback, */
126 /* widget); */
127
128 //begin copy paste extravaganza!!!
129
130 //GtkFixed *fixed = GTK_FIXED (widget);
131 //GtkFixedPrivate *priv = fixed->priv;
132
133
134 gtk_widget_set_allocation (widget, allocation);
135
136 if (gtk_widget_get_has_window (widget))
137 {
138 if (gtk_widget_get_realized (widget))
139 gdk_window_move_resize (gtk_widget_get_window (widget),
140 allocation->x,
141 allocation->y,
142 allocation->width,
143 allocation->height);
144 }
145
146 for (children = priv->children;
147 children;
148 children = children->next)
149 {
150 child = children->data;
151
152 if (!gtk_widget_get_visible (child->widget))
153 continue;
154
155 gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
156 child_allocation.x = child->x;
157 child_allocation.y = child->y;
158
159 if (!gtk_widget_get_has_window (widget))
160 {
161 child_allocation.x += allocation->x;
162 child_allocation.y += allocation->y;
163 }
164
165 child_allocation.width = child_requisition.width;
166 child_allocation.height = child_requisition.height;
167
168
169
170 xv = (struct xwidget_view*) g_object_get_data (G_OBJECT (child->widget), XG_XWIDGET_VIEW);
171 //printf("aloc callback %d %s\n", xv, gtk_widget_get_name(child));
172 if(xv){
173 //gtk_widget_get_allocation(child, &child_allocation);
174 child_allocation.width = xv->clip_right;
175 child_allocation.height = xv->clip_bottom - xv->clip_top;
176 //gtk_widget_size_allocate (child, &child_allocation);
177 //TODO find a way to remove this feeble workaround
178 // printf(" allocation internal modification for xw %d %d,%d\n",xv, child_allocation.width, child_allocation.height);
179
180 }
181 gtk_widget_size_allocate (child->widget, &child_allocation);
182
183 }
184
185 }
186
187 #endif /* HAVE_XWIDGETS */
188
189 static void
190 emacs_fixed_class_init (EmacsFixedClass *klass)
191 {
192 GtkWidgetClass *widget_class;
193 GtkFixedClass *fixed_class;
194
195 widget_class = (GtkWidgetClass*) klass;
196 fixed_class = (GtkFixedClass*) klass;
197
198 widget_class->get_preferred_width = emacs_fixed_get_preferred_width;
199 widget_class->get_preferred_height = emacs_fixed_get_preferred_height;
200 #ifdef HAVE_XWIDGETS
201 widget_class->size_allocate = emacs_fixed_gtk_widget_size_allocate;
202 #endif
203 g_type_class_add_private (klass, sizeof (EmacsFixedPrivate));
204 }
205
206 static GType
207 emacs_fixed_child_type (GtkFixed *container)
208 {
209 return GTK_TYPE_WIDGET;
210 }
211
212 static void
213 emacs_fixed_init (EmacsFixed *fixed)
214 {
215 fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, EMACS_TYPE_FIXED,
216 EmacsFixedPrivate);
217 fixed->priv->f = 0;
218 }
219
220 /**
221 * emacs_fixed_new:
222 *
223 * Creates a new #EmacsFixed.
224 *
225 * Returns: a new #EmacsFixed.
226 */
227 GtkWidget*
228 emacs_fixed_new (struct frame *f)
229 {
230 EmacsFixed *fixed = g_object_new (EMACS_TYPE_FIXED, NULL);
231 EmacsFixedPrivate *priv = fixed->priv;
232 priv->f = f;
233 return GTK_WIDGET (fixed);
234 }
235
236 static void
237 emacs_fixed_get_preferred_width (GtkWidget *widget,
238 gint *minimum,
239 gint *natural)
240 {
241 EmacsFixed *fixed = EMACS_FIXED (widget);
242 EmacsFixedPrivate *priv = fixed->priv;
243 int w = priv->f->output_data.x->size_hints.min_width;
244 if (minimum) *minimum = w;
245 if (natural) *natural = w;
246 }
247
248 static void
249 emacs_fixed_get_preferred_height (GtkWidget *widget,
250 gint *minimum,
251 gint *natural)
252 {
253 EmacsFixed *fixed = EMACS_FIXED (widget);
254 EmacsFixedPrivate *priv = fixed->priv;
255 int h = priv->f->output_data.x->size_hints.min_height;
256 if (minimum) *minimum = h;
257 if (natural) *natural = h;
258 }
259
260
261 /* Override the X function so we can intercept Gtk+ 3 calls.
262 Use our values for min_width/height so that KDE don't freak out
263 (Bug#8919), and so users can resize our frames as they wish. */
264
265 void
266 XSetWMSizeHints (Display* d,
267 Window w,
268 XSizeHints* hints,
269 Atom prop)
270 {
271 struct x_display_info *dpyinfo = x_display_info_for_display (d);
272 struct frame *f = x_top_window_to_frame (dpyinfo, w);
273 long data[18];
274 data[0] = hints->flags;
275 data[1] = hints->x;
276 data[2] = hints->y;
277 data[3] = hints->width;
278 data[4] = hints->height;
279 data[5] = hints->min_width;
280 data[6] = hints->min_height;
281 data[7] = hints->max_width;
282 data[8] = hints->max_height;
283 data[9] = hints->width_inc;
284 data[10] = hints->height_inc;
285 data[11] = hints->min_aspect.x;
286 data[12] = hints->min_aspect.y;
287 data[13] = hints->max_aspect.x;
288 data[14] = hints->max_aspect.y;
289 data[15] = hints->base_width;
290 data[16] = hints->base_height;
291 data[17] = hints->win_gravity;
292
293 if ((hints->flags & PMinSize) && f)
294 {
295 int w = f->output_data.x->size_hints.min_width;
296 int h = f->output_data.x->size_hints.min_height;
297 data[5] = w;
298 data[6] = h;
299 }
300
301 XChangeProperty (d, w, prop, XA_WM_SIZE_HINTS, 32, PropModeReplace,
302 (unsigned char *) data, 18);
303 }
304
305 /* Override this X11 function.
306 This function is in the same X11 file as the one above. So we must
307 provide it also. */
308
309 void
310 XSetWMNormalHints (Display *d, Window w, XSizeHints *hints)
311 {
312 XSetWMSizeHints (d, w, hints, XA_WM_NORMAL_HINTS);
313 }