Ejemplo n.º 1
0
static void
gtk_application_window_real_get_preferred_width_for_height (GtkWidget *widget,
                                                            gint       height,
                                                            gint      *minimum_width,
                                                            gint      *natural_width)
{
  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget);
  gint menubar_height;

  if (window->priv->menubar != NULL)
    gtk_widget_get_preferred_height (window->priv->menubar, &menubar_height, NULL);
  else
    menubar_height = 0;

  GTK_WIDGET_CLASS (gtk_application_window_parent_class)
    ->get_preferred_width_for_height (widget, height - menubar_height, minimum_width, natural_width);

  if (window->priv->menubar != NULL)
    {
      gint menubar_min_width, menubar_nat_width;
      gint border_width;
      GtkBorder border = { 0 };

      gtk_widget_get_preferred_width_for_height (window->priv->menubar, menubar_height, &menubar_min_width, &menubar_nat_width);

      border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
      _gtk_window_get_shadow_width (GTK_WINDOW (widget), &border);

      menubar_min_width += 2 * border_width + border.left + border.right;
      menubar_nat_width += 2 * border_width + border.left + border.right;

      *minimum_width = MAX (*minimum_width, menubar_min_width);
      *natural_width = MAX (*natural_width, menubar_nat_width);
    }
}
Ejemplo n.º 2
0
/* Ignores (x, y) on input, translates event coordinates to
 * allocation relative (x, y) of the returned widget.
 */
static GtkWidget *
find_topmost_widget_coords_from_event (GdkEvent *event,
				       gint     *x,
				       gint     *y)
{
  GtkAllocation allocation;
  gint tx, ty;
  gdouble dx, dy;
  GtkWidget *tmp;

  gdk_event_get_coords (event, &dx, &dy);

  /* Returns coordinates relative to tmp's allocation. */
  tmp = _gtk_widget_find_at_coords (event->any.window, dx, dy, &tx, &ty);

  if (!tmp)
    return NULL;

  /* Make sure the pointer can actually be on the widget returned. */
  gtk_widget_get_allocation (tmp, &allocation);
  allocation.x = 0;
  allocation.y = 0;
  if (GTK_IS_WINDOW (tmp))
    {
      GtkBorder border;
      _gtk_window_get_shadow_width (GTK_WINDOW (tmp), &border);
      allocation.x = border.left;
      allocation.y = border.top;
      allocation.width -= border.left + border.right;
      allocation.height -= border.top + border.bottom;
    }

  if (tx < allocation.x || tx >= allocation.width ||
      ty < allocation.y || ty >= allocation.height)
    return NULL;

  if (x)
    *x = tx;
  if (y)
    *y = ty;

  return tmp;
}
Ejemplo n.º 3
0
static void
get_bounding_box (GtkWidget    *widget,
                  GdkRectangle *bounds)
{
  GtkAllocation allocation;
  GtkBorder border = { 0, };
  GdkWindow *window;
  gint x, y;
  gint w, h;
  gint x1, y1;
  gint x2, y2;
  gint x3, y3;
  gint x4, y4;

  window = gtk_widget_get_parent_window (widget);
  if (window == NULL)
    window = gtk_widget_get_window (widget);

  gtk_widget_get_allocation (widget, &allocation);
  if (GTK_IS_WINDOW (widget))
    _gtk_window_get_shadow_width (GTK_WINDOW (widget), &border);
  x = allocation.x + border.left;
  y = allocation.y + border.right;
  w = allocation.width - border.left - border.right;
  h = allocation.height - border.top - border.bottom;

  gdk_window_get_root_coords (window, x, y, &x1, &y1);
  gdk_window_get_root_coords (window, x + w, y, &x2, &y2);
  gdk_window_get_root_coords (window, x, y + h, &x3, &y3);
  gdk_window_get_root_coords (window, x + w, y + h, &x4, &y4);

#define MIN4(a,b,c,d) MIN(MIN(a,b),MIN(c,d))
#define MAX4(a,b,c,d) MAX(MAX(a,b),MAX(c,d))

  bounds->x = floor (MIN4 (x1, x2, x3, x4));
  bounds->y = floor (MIN4 (y1, y2, y3, y4));
  bounds->width = ceil (MAX4 (x1, x2, x3, x4)) - bounds->x;
  bounds->height = ceil (MAX4 (y1, y2, y3, y4)) - bounds->y;
}
Ejemplo n.º 4
0
static void
gtk_tooltip_position (GtkTooltip *tooltip,
		      GdkDisplay *display,
		      GtkWidget  *new_tooltip_widget)
{
  gint x, y, width, height;
  GdkScreen *screen;
  gint monitor_num;
  GdkRectangle monitor;
  guint cursor_size;
  GdkRectangle bounds;
  GtkBorder border;

#define MAX_DISTANCE 32

  gtk_widget_realize (GTK_WIDGET (tooltip->current_window));
  gtk_widget_set_visible (GTK_WIDGET (tooltip->current_window), TRUE);

  tooltip->tooltip_widget = new_tooltip_widget;

  screen = gtk_widget_get_screen (new_tooltip_widget);

  _gtk_window_get_shadow_width (GTK_WINDOW (tooltip->current_window), &border);

  width = gtk_widget_get_allocated_width (GTK_WIDGET (tooltip->current_window)) - border.left - border.right;
  height = gtk_widget_get_allocated_height (GTK_WIDGET (tooltip->current_window)) - border.top - border.bottom;

  monitor_num = gdk_screen_get_monitor_at_point (screen,
                                                 tooltip->last_x,
                                                 tooltip->last_y);
  gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor);

  get_bounding_box (new_tooltip_widget, &bounds);

  /* Position the tooltip */

  cursor_size = gdk_display_get_default_cursor_size (display);

  /* Try below */
  x = bounds.x + bounds.width / 2 - width / 2;
  y = bounds.y + bounds.height + 4;

  if (y + height <= monitor.y + monitor.height)
    {
      if (tooltip->keyboard_mode_enabled)
        goto found;

      if (y <= tooltip->last_y + cursor_size + MAX_DISTANCE)
        {
          if (tooltip->last_x + cursor_size + MAX_DISTANCE < x)
            x = tooltip->last_x + cursor_size + MAX_DISTANCE;
          else if (x + width < tooltip->last_x - MAX_DISTANCE)
            x = tooltip->last_x - MAX_DISTANCE - width;

          goto found;
        }
   }

  /* Try above */
  x = bounds.x + bounds.width / 2 - width / 2;
  y = bounds.y - height - 4;

  if (y >= monitor.y)
    {
      if (tooltip->keyboard_mode_enabled)
        goto found;

      if (y + height >= tooltip->last_y - MAX_DISTANCE)
        {
          if (tooltip->last_x + cursor_size + MAX_DISTANCE < x)
            x = tooltip->last_x + cursor_size + MAX_DISTANCE;
          else if (x + width < tooltip->last_x - MAX_DISTANCE)
            x = tooltip->last_x - MAX_DISTANCE - width;

          goto found;
        }
    }

  /* Try right FIXME: flip on rtl ? */
  x = bounds.x + bounds.width + 4;
  y = bounds.y + bounds.height / 2 - height / 2;

  if (x + width <= monitor.x + monitor.width)
    {
      if (tooltip->keyboard_mode_enabled)
        goto found;

      if (x <= tooltip->last_x + cursor_size + MAX_DISTANCE)
        {
          if (tooltip->last_y + cursor_size + MAX_DISTANCE < y)
            y = tooltip->last_y + cursor_size + MAX_DISTANCE;
          else if (y + height < tooltip->last_y - MAX_DISTANCE)
            y = tooltip->last_y - MAX_DISTANCE - height;

          goto found;
        }
    }

  /* Try left FIXME: flip on rtl ? */
  x = bounds.x - width - 4;
  y = bounds.y + bounds.height / 2 - height / 2;

  if (x >= monitor.x)
    {
      if (tooltip->keyboard_mode_enabled)
        goto found;

      if (x + width >= tooltip->last_x - MAX_DISTANCE)
        {
          if (tooltip->last_y + cursor_size + MAX_DISTANCE < y)
            y = tooltip->last_y + cursor_size + MAX_DISTANCE;
          else if (y + height < tooltip->last_y - MAX_DISTANCE)
            y = tooltip->last_y - MAX_DISTANCE - height;

          goto found;
        }
    }

   /* Fallback */
  if (tooltip->keyboard_mode_enabled)
    {
      x = bounds.x + bounds.width / 2 - width / 2;
      y = bounds.y + bounds.height + 4;
    }
  else
    {
      /* At cursor */
      x = tooltip->last_x + cursor_size * 3 / 4;
      y = tooltip->last_y + cursor_size * 3 / 4;
    }

found:
  /* Show it */
  if (tooltip->current_window)
    {
      if (x + width > monitor.x + monitor.width)
        x -= x - (monitor.x + monitor.width) + width;
      else if (x < monitor.x)
        x = monitor.x;

      if (y + height > monitor.y + monitor.height)
        y -= y - (monitor.y + monitor.height) + height;
      else if (y < monitor.y)
        y = monitor.y;

      if (!tooltip->keyboard_mode_enabled)
        {
          /* don't pop up under the pointer */
          if (x <= tooltip->last_x && tooltip->last_x < x + width &&
              y <= tooltip->last_y && tooltip->last_y < y + height)
            y = tooltip->last_y - height - 2;
        }

#ifdef GDK_WINDOWING_WAYLAND
      /* set the transient parent on the tooltip when running with the Wayland
       * backend to allow correct positioning of the tooltip windows */
      if (GDK_IS_WAYLAND_DISPLAY (display))
        {
          GtkWidget *toplevel;

          toplevel = gtk_widget_get_toplevel (tooltip->tooltip_widget);
          if (GTK_IS_WINDOW (toplevel))
            gtk_window_set_transient_for (GTK_WINDOW (tooltip->current_window),
                                          GTK_WINDOW (toplevel));
        }
#endif

      x -= border.left;
      y -= border.top;

      gtk_window_move (GTK_WINDOW (tooltip->current_window), x, y);
      gtk_widget_show (GTK_WIDGET (tooltip->current_window));
    }
}