/* A Gtk Widget that inherits GtkFixed, but can be shrinked.
This file is only use when compiling with Gtk+ 3.
Copyright (C) 2011 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see . */
#include
#include "emacsgtkfixed.h"
#include
#include
#include
#include "lisp.h"
#include "frame.h"
#include "xterm.h"
#ifdef HAVE_XWIDGETS
#include "xwidget.h"
#endif
struct _EmacsFixedPrivate
{
struct frame *f;
};
static void emacs_fixed_get_preferred_width (GtkWidget *widget,
gint *minimum,
gint *natural);
static void emacs_fixed_get_preferred_height (GtkWidget *widget,
gint *minimum,
gint *natural);
G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED)
#ifdef HAVE_XWIDGETS
/* void aloc_callback(GtkWidget* child, GtkWidget* fixed){ */
/* GtkAllocation child_allocation; */
/* GtkRequisition child_requisition; */
/* //TODO */
/* // if child is an xwidget, find its clipping area and modify allocation */
/* struct xwidget_view* xv = (struct xwidget_view*) g_object_get_data (G_OBJECT (child), XG_XWIDGET_VIEW); */
/* printf("aloc callback %d %s\n", xv, gtk_widget_get_name(child)); */
/* if(xv){ */
/* printf(" allocation modification for xw\n"); */
/* gtk_widget_get_allocation(child, &child_allocation); */
/* child_allocation.width = xv->clip_right; */
/* child_allocation.height = xv->clip_bottom - xv->clip_top; */
/* gtk_widget_size_allocate (child, &child_allocation); */
/* //TODO find a way to remove this feeble workaround */
/* } */
/* } */
struct GtkFixedPrivateL
{
GList *children;
};
static void emacs_fixed_gtk_widget_size_allocate (GtkWidget *widget,
GtkAllocation *allocation){
//for xwidgets
//TODO 1st call base class method
EmacsFixedClass *klass;
GtkWidgetClass *parent_class;
struct GtkFixedPrivateL* priv;
GtkFixedChild *child;
GtkAllocation child_allocation;
GtkRequisition child_requisition;
GList *children;
struct xwidget_view* xv;
// printf(" emacs_fixed_gtk_widget_size_allocate\n");
klass = EMACS_FIXED_GET_CLASS (widget);
parent_class = g_type_class_peek_parent (klass);
parent_class->size_allocate (widget, allocation);
priv = G_TYPE_INSTANCE_GET_PRIVATE (widget,
GTK_TYPE_FIXED,
struct GtkFixedPrivateL);
//fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, GTK_TYPE_FIXED, GtkFixedPrivate);
//then modify allocations
/* gtk_container_foreach (widget, */
/* aloc_callback, */
/* widget); */
//begin copy paste extravaganza!!!
//GtkFixed *fixed = GTK_FIXED (widget);
//GtkFixedPrivate *priv = fixed->priv;
gtk_widget_set_allocation (widget, allocation);
if (gtk_widget_get_has_window (widget))
{
if (gtk_widget_get_realized (widget))
gdk_window_move_resize (gtk_widget_get_window (widget),
allocation->x,
allocation->y,
allocation->width,
allocation->height);
}
for (children = priv->children;
children;
children = children->next)
{
child = children->data;
if (!gtk_widget_get_visible (child->widget))
continue;
gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
child_allocation.x = child->x;
child_allocation.y = child->y;
if (!gtk_widget_get_has_window (widget))
{
child_allocation.x += allocation->x;
child_allocation.y += allocation->y;
}
child_allocation.width = child_requisition.width;
child_allocation.height = child_requisition.height;
xv = (struct xwidget_view*) g_object_get_data (G_OBJECT (child->widget), XG_XWIDGET_VIEW);
//printf("aloc callback %d %s\n", xv, gtk_widget_get_name(child));
if(xv){
//gtk_widget_get_allocation(child, &child_allocation);
child_allocation.width = xv->clip_right;
child_allocation.height = xv->clip_bottom - xv->clip_top;
//gtk_widget_size_allocate (child, &child_allocation);
//TODO find a way to remove this feeble workaround
// printf(" allocation internal modification for xw %d %d,%d\n",xv, child_allocation.width, child_allocation.height);
}
gtk_widget_size_allocate (child->widget, &child_allocation);
}
}
#endif
static void
emacs_fixed_class_init (EmacsFixedClass *klass)
{
GtkWidgetClass *widget_class;
GtkFixedClass *fixed_class;
widget_class = (GtkWidgetClass*) klass;
fixed_class = (GtkFixedClass*) klass;
widget_class->get_preferred_width = emacs_fixed_get_preferred_width;
widget_class->get_preferred_height = emacs_fixed_get_preferred_height;
#ifdef HAVE_XWIDGETS
widget_class->size_allocate = emacs_fixed_gtk_widget_size_allocate;
#endif
g_type_class_add_private (klass, sizeof (EmacsFixedPrivate));
}
static GType
emacs_fixed_child_type (GtkFixed *container)
{
return GTK_TYPE_WIDGET;
}
static void
emacs_fixed_init (EmacsFixed *fixed)
{
fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, EMACS_TYPE_FIXED,
EmacsFixedPrivate);
fixed->priv->f = 0;
}
/**
* emacs_fixed_new:
*
* Creates a new #EmacsFixed.
*
* Returns: a new #EmacsFixed.
*/
GtkWidget*
emacs_fixed_new (struct frame *f)
{
EmacsFixed *fixed = g_object_new (EMACS_TYPE_FIXED, NULL);
EmacsFixedPrivate *priv = fixed->priv;
priv->f = f;
return GTK_WIDGET (fixed);
}
static void
emacs_fixed_get_preferred_width (GtkWidget *widget,
gint *minimum,
gint *natural)
{
EmacsFixed *fixed = EMACS_FIXED (widget);
EmacsFixedPrivate *priv = fixed->priv;
int w = priv->f->output_data.x->size_hints.min_width;
if (minimum) *minimum = w;
if (natural) *natural = w;
}
static void
emacs_fixed_get_preferred_height (GtkWidget *widget,
gint *minimum,
gint *natural)
{
EmacsFixed *fixed = EMACS_FIXED (widget);
EmacsFixedPrivate *priv = fixed->priv;
int h = priv->f->output_data.x->size_hints.min_height;
if (minimum) *minimum = h;
if (natural) *natural = h;
}
/* Override the X function so we can intercept Gtk+ 3 calls.
Use our values for min_width/height so that KDE don't freak out
(Bug#8919), and so users can resize our frames as they wish. */
void
XSetWMSizeHints(Display* d,
Window w,
XSizeHints* hints,
Atom prop)
{
struct x_display_info *dpyinfo = x_display_info_for_display (d);
struct frame *f = x_top_window_to_frame (dpyinfo, w);
long data[18];
data[0] = hints->flags;
data[1] = hints->x;
data[2] = hints->y;
data[3] = hints->width;
data[4] = hints->height;
data[5] = hints->min_width;
data[6] = hints->min_height;
data[7] = hints->max_width;
data[8] = hints->max_height;
data[9] = hints->width_inc;
data[10] = hints->height_inc;
data[11] = hints->min_aspect.x;
data[12] = hints->min_aspect.y;
data[13] = hints->max_aspect.x;
data[14] = hints->max_aspect.y;
data[15] = hints->base_width;
data[16] = hints->base_height;
data[17] = hints->win_gravity;
if ((hints->flags & PMinSize) && f)
{
int w = f->output_data.x->size_hints.min_width;
int h = f->output_data.x->size_hints.min_height;
data[5] = w;
data[6] = h;
}
XChangeProperty (d, w, prop, XA_WM_SIZE_HINTS, 32, PropModeReplace,
(unsigned char *) data, 18);
}
/* Override this X11 function.
This function is in the same X11 file as the one above. So we must
provide it also. */
void
XSetWMNormalHints (Display *d, Window w, XSizeHints *hints)
{
XSetWMSizeHints (d, w, hints, XA_WM_NORMAL_HINTS);
}