static void
gstyle_eyedropper_pointer_motion_notify_cb (GstyleEyedropper *self,
                                            GdkEventMotion   *event,
                                            GtkWindow        *window)
{
  GdkRGBA rgba;
  gint x_root, y_root;
  gint x, y;

  g_assert (GSTYLE_IS_EYEDROPPER (self));
  g_assert (GTK_IS_WINDOW (window));
  g_assert (event != NULL);
  g_assert (self->screen == gdk_event_get_screen ((GdkEvent *) event));

  gstyle_eyedropper_event_get_root_coords (self, (GdkEvent *)event, &x_root, &y_root);
  gstyle_eyedropper_calculate_window_position (self, GTK_WINDOW (self->window), event->x_root, event->y_root, &x, &y);
  gtk_window_move (GTK_WINDOW (self->window), x, y);

  gstyle_eyedropper_draw_zoom_area (self, event->x_root, event->y_root);
  get_rgba_at_cursor (self,
                      self->screen,
                      gdk_event_get_device ((GdkEvent *) event),
                      event->x_root, event->y_root, &rgba);

  gstyle_color_set_rgba (self->color, &rgba);
  if (self->button_pressed)
    g_signal_emit (self, signals [COLOR_PICKED], 0, &rgba);
}
static gboolean
password_dialog_grab_keyboard (GtkWidget *widget,
    GdkEvent *event,
    gpointer user_data)
{
  EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (user_data)->priv;

  if (!priv->grabbing)
    {
      GdkDevice *device = gdk_event_get_device (event);

      if (device != NULL)
        {
          GdkGrabStatus status = gdk_device_grab (device,
              gtk_widget_get_window (widget),
              GDK_OWNERSHIP_WINDOW,
              FALSE,
              GDK_ALL_EVENTS_MASK,
              NULL,
              gdk_event_get_time (event));

          if (status != GDK_GRAB_SUCCESS)
            DEBUG ("Could not grab keyboard; grab status was %u", status);
          else
            priv->grabbing = TRUE;
        }
      else
        DEBUG ("Could not get the event device!");
    }

  return FALSE;
}
Example #3
0
static gboolean
on_widget_button_press (GtkWidget *widget,
			GdkEventButton *event,
			char *item_id)
{
  GdkDevice *device = gdk_event_get_device ((GdkEvent*) event);

  g_print ("%s received 'button-press' signal\n", item_id);

  if (device && strstr (item_id, "explicit"))
    {
      GdkGrabStatus status;
      GdkEventMask mask = GDK_BUTTON_PRESS_MASK
	| GDK_BUTTON_RELEASE_MASK
	| GDK_POINTER_MOTION_MASK
	| GDK_POINTER_MOTION_HINT_MASK
	| GDK_ENTER_NOTIFY_MASK
	| GDK_LEAVE_NOTIFY_MASK;

      status = gdk_device_grab (device, gtk_widget_get_window (widget),
				GDK_OWNERSHIP_NONE, FALSE, mask,
				NULL, event->time);
      if (status == GDK_GRAB_SUCCESS)
	g_print ("grabbed pointer\n");
      else
	g_print ("pointer grab failed\n");
    }

  return TRUE;
}
Example #4
0
static void
on_highlight_widget (GtkWidget          *button,
                     GdkEvent           *event,
                     GtkInspectorWindow *iw)
{
  GtkWidget *widget;

  widget = find_widget_at_pointer (gdk_event_get_device (event));

  if (widget == NULL)
    {
      /* This window isn't in-process. Ignore it. */
      return;
    }

  if (gtk_widget_get_toplevel (widget) == GTK_WIDGET (iw))
    {
      /* Don't hilight things in the inspector window */
      return;
    }

  if (iw->flash_widget == widget)
    {
      /* Already selected */
      return;
    }

  clear_flash (iw);
  start_flash (iw, widget);
}
Example #5
0
void
gw_spellcheck_record_mouse_cordinates (GwSpellcheck *spellcheck, 
                                       GdkEvent     *event)
{
    GwSpellcheckPrivate *priv;
    GtkWidget *toplevel;
    gint toplevel_x, toplevel_y;

    priv = spellcheck->priv;
    toplevel = GTK_WIDGET (gtk_widget_get_ancestor (GTK_WIDGET (priv->entry), GTK_TYPE_WINDOW));

    gdk_window_get_device_position (
      gtk_widget_get_window (GTK_WIDGET (priv->entry)),
      gdk_event_get_device (event),
      &toplevel_x, 
      &toplevel_y, 
      NULL
    );

    gtk_widget_translate_coordinates (
      toplevel, 
      GTK_WIDGET (priv->entry), 
      toplevel_x, 
      toplevel_y, 
      &priv->x, 
      &priv->y
    );
}
static gboolean
gstyle_eyedropper_pointer_released_cb (GstyleEyedropper *self,
                                       GdkEventButton   *event,
                                       GtkWindow        *window)
{
  GdkRGBA rgba;

  g_assert (GSTYLE_IS_EYEDROPPER (self));
  g_assert (event != NULL);
  g_assert (GTK_IS_WINDOW (window));
  g_assert (self->screen == gdk_event_get_screen ((GdkEvent *) event));

  get_rgba_at_cursor (self,
                      self->screen,
                      gdk_event_get_device ((GdkEvent *) event),
                      event->x_root, event->y_root, &rgba);

  gstyle_color_set_rgba (self->color, &rgba);
  g_signal_emit (self, signals [COLOR_PICKED], 0, &rgba);

  release_grab (self);
  self->button_pressed = FALSE;

  return GDK_EVENT_STOP;
}
Example #7
0
static gboolean
pointer_on_link (TTXWindow *self, GtkWidget *w, GdkEvent *event,
	 unsigned *page, unsigned *subpage)
{
	GSList *cur;
	GdkWindow *win;
	GdkDevice *dev;
	guint x, y;

	dev = gdk_event_get_device (event);
	win = gtk_widget_get_window (w);

	gdk_window_get_device_position (win, dev, (int*)&x, (int*)&y, NULL);

	for (cur = self->priv->links; cur; cur = g_slist_next (cur)) {

		TTXLink *link;
		link = (TTXLink*)cur->data;

		if (link->left <= x && x <= link->right &&
		    link->top  <= y && y <= link-> bottom) {
			*page	 = link->page;
			*subpage = link->subpage;
			return TRUE;
		}
	}

	return FALSE;
}
Example #8
0
void GtkPopupMenu::popUp(const IntSize& menuSize, const IntPoint& menuPosition, int itemCount, int selectedItem, const GdkEvent* event)
{
    resetTypeAheadFindState();
    m_menuPosition = menuPosition;
    gtk_menu_set_active(GTK_MENU(m_popup.get()), selectedItem);

    // This approach follows the one in gtkcombobox.c.
    GtkRequisition requisition;
    gtk_widget_set_size_request(m_popup.get(), -1, -1);
#ifdef GTK_API_VERSION_2
    gtk_widget_size_request(m_popup.get(), &requisition);
#else
    gtk_widget_get_preferred_size(m_popup.get(), &requisition, 0);
#endif

    gtk_widget_set_size_request(m_popup.get(), std::max(menuSize.width(), requisition.width), -1);

    GList* children = gtk_container_get_children(GTK_CONTAINER(m_popup.get()));
    GList* p = children;
    if (itemCount) {
        for (int i = 0; i < itemCount; i++) {
            if (i > selectedItem)
                break;

            GtkWidget* item = reinterpret_cast<GtkWidget*>(p->data);
            GtkRequisition itemRequisition;
#ifdef GTK_API_VERSION_2
            gtk_widget_get_child_requisition(item, &itemRequisition);
#else
            gtk_widget_get_preferred_size(item, &itemRequisition, 0);
#endif
            m_menuPosition.setY(m_menuPosition.y() - itemRequisition.height);

            p = g_list_next(p);
        }
    } else {
        // Center vertically the empty popup in the combo box area.
        m_menuPosition.setY(m_menuPosition.y() - menuSize.height() / 2);
    }
    g_list_free(children);

    guint button;
    guint32 activateTime;
    if (event) {
        button = event->type == GDK_BUTTON_PRESS ? event->button.button : 1;
        activateTime = gdk_event_get_time(event);
    } else {
        button = 1;
        activateTime = GDK_CURRENT_TIME;
    }

#ifdef GTK_API_VERSION_2
    gtk_menu_popup(GTK_MENU(m_popup.get()), 0, 0, reinterpret_cast<GtkMenuPositionFunc>(menuPositionFunction), this, button, activateTime);
#else
    gtk_menu_popup_for_device(GTK_MENU(m_popup.get()), event ? gdk_event_get_device(event) : 0, 0, 0,
                              reinterpret_cast<GtkMenuPositionFunc>(menuPositionFunction), this, 0, button, activateTime);
#endif
}
void WebPopupMenuProxyGtk::showPopupMenu(const IntRect& rect, TextDirection, double /* pageScaleFactor */, const Vector<WebPopupItem>& items, const PlatformPopupMenuData&, int32_t selectedIndex)
{
    populatePopupMenu(items);
    gtk_menu_set_active(GTK_MENU(m_popup), selectedIndex);

    resetTypeAheadFindState();


    IntPoint menuPosition = convertWidgetPointToScreenPoint(m_webView, rect.location());
    menuPosition.move(0, rect.height());

    // This approach follows the one in gtkcombobox.c.
    GtkRequisition requisition;
    gtk_widget_set_size_request(m_popup, -1, -1);
    gtk_widget_get_preferred_size(m_popup, &requisition, nullptr);
    gtk_widget_set_size_request(m_popup, std::max(rect.width(), requisition.width), -1);

    if (int itemCount = items.size()) {
        GUniquePtr<GList> children(gtk_container_get_children(GTK_CONTAINER(m_popup)));
        int i;
        GList* child;
        for (i = 0, child = children.get(); i < itemCount; i++, child = g_list_next(child)) {
            if (i > selectedIndex)
                break;

            GtkWidget* item = GTK_WIDGET(child->data);
            GtkRequisition itemRequisition;
            gtk_widget_get_preferred_size(item, &itemRequisition, nullptr);
            menuPosition.setY(menuPosition.y() - itemRequisition.height);
        }
    } else {
        // Center vertically the empty popup in the combo box area.
        menuPosition.setY(menuPosition.y() - rect.height() / 2);
    }

    const GdkEvent* event = m_client->currentlyProcessedMouseDownEvent() ? m_client->currentlyProcessedMouseDownEvent()->nativeEvent() : nullptr;
    gtk_menu_popup_for_device(GTK_MENU(m_popup), event ? gdk_event_get_device(event) : nullptr, nullptr, nullptr,
        [](GtkMenu*, gint* x, gint* y, gboolean* pushIn, gpointer userData) {
            // We can pass a pointer to the menuPosition local variable because the nested main loop ensures this is called in the function context.
            IntPoint* menuPosition = static_cast<IntPoint*>(userData);
            *x = menuPosition->x();
            *y = menuPosition->y();
            *pushIn = menuPosition->y() < 0;
        }, &menuPosition, nullptr, event && event->type == GDK_BUTTON_PRESS ? event->button.button : 1,
        event ? gdk_event_get_time(event) : GDK_CURRENT_TIME);

    // Now that the menu has a position, schedule a resize to make sure it's resized to fit vertically in the work area.
    gtk_widget_queue_resize(m_popup);

    // PopupMenu can fail to open when there is no mouse grab.
    // Ensure WebCore does not go into some pesky state.
    if (!gtk_widget_get_visible(m_popup)) {
       m_client->failedToShowPopupMenu();
       return;
    }
}
Example #10
0
void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& event, bool wasEventHandled)
{
    if (wasEventHandled)
        return;

#if HAVE(GTK_GESTURES)
    GestureController& gestureController = webkitWebViewBaseGestureController(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
    if (gestureController.handleEvent(event.nativeEvent()))
        return;
#endif

    // Emulate pointer events if unhandled.
    const GdkEvent* touchEvent = event.nativeEvent();

    if (!touchEvent->touch.emulating_pointer)
        return;

    GUniquePtr<GdkEvent> pointerEvent;

    if (touchEvent->type == GDK_TOUCH_UPDATE) {
        pointerEvent.reset(gdk_event_new(GDK_MOTION_NOTIFY));
        pointerEvent->motion.time = touchEvent->touch.time;
        pointerEvent->motion.x = touchEvent->touch.x;
        pointerEvent->motion.y = touchEvent->touch.y;
        pointerEvent->motion.x_root = touchEvent->touch.x_root;
        pointerEvent->motion.y_root = touchEvent->touch.y_root;
        pointerEvent->motion.state = touchEvent->touch.state | GDK_BUTTON1_MASK;
    } else {
        switch (touchEvent->type) {
        case GDK_TOUCH_END:
            pointerEvent.reset(gdk_event_new(GDK_BUTTON_RELEASE));
            pointerEvent->button.state = touchEvent->touch.state | GDK_BUTTON1_MASK;
            break;
        case GDK_TOUCH_BEGIN:
            pointerEvent.reset(gdk_event_new(GDK_BUTTON_PRESS));
            break;
        default:
            ASSERT_NOT_REACHED();
        }

        pointerEvent->button.button = 1;
        pointerEvent->button.time = touchEvent->touch.time;
        pointerEvent->button.x = touchEvent->touch.x;
        pointerEvent->button.y = touchEvent->touch.y;
        pointerEvent->button.x_root = touchEvent->touch.x_root;
        pointerEvent->button.y_root = touchEvent->touch.y_root;
    }

    gdk_event_set_device(pointerEvent.get(), gdk_event_get_device(touchEvent));
    gdk_event_set_source_device(pointerEvent.get(), gdk_event_get_source_device(touchEvent));
    pointerEvent->any.window = GDK_WINDOW(g_object_ref(touchEvent->any.window));
    pointerEvent->any.send_event = TRUE;

    gtk_widget_event(m_viewWidget, pointerEvent.get());
}
Example #11
0
static gboolean
on_widget_motion_notify (GtkWidget *widget,
			 GdkEventMotion *event,
			 char *item_id)
{
  GdkDevice *device = gdk_event_get_device ((GdkEvent*) event);

  g_print ("%s received 'motion-notify' signal (window: %p)\n", item_id,
	   event->window);

  if (event->is_hint && device)
    gdk_window_get_device_position (event->window, device, NULL, NULL, NULL);

  return TRUE;
}
Example #12
0
static gboolean
property_query_event (GtkWidget *widget,
                      GdkEvent  *event,
                      gpointer   data)
{
  GtkInspectorWindow *iw = (GtkInspectorWindow *)data;

  if (event->type == GDK_BUTTON_RELEASE)
    {
      g_signal_handlers_disconnect_by_func (widget, property_query_event, data);
      gtk_grab_remove (widget);
      gdk_device_ungrab (gdk_event_get_device (event), GDK_CURRENT_TIME);
      on_inspect_widget (widget, event, data);
    }
  else if (event->type == GDK_MOTION_NOTIFY)
    {
      on_highlight_widget (widget, event, data);
    }
  else if (event->type == GDK_KEY_PRESS)
    {
      GdkEventKey *ke = (GdkEventKey*)event;
      GdkDevice *device;

      if (ke->keyval == GDK_KEY_Escape)
        {
          g_signal_handlers_disconnect_by_func (widget, property_query_event, data);
          gtk_grab_remove (widget);
          device = gdk_device_get_associated_device (gdk_event_get_device (event));
          gdk_device_ungrab (device, GDK_CURRENT_TIME);
          gdk_window_raise (gtk_widget_get_window (GTK_WIDGET (iw)));
          clear_flash (iw);
        }
    }

  return TRUE;
}
Example #13
0
static void
on_inspect_widget (GtkWidget          *button,
                   GdkEvent           *event,
                   GtkInspectorWindow *iw)
{
  GtkWidget *widget;

  gdk_window_raise (gtk_widget_get_window (GTK_WIDGET (iw)));

  clear_flash (iw);

  widget = find_widget_at_pointer (gdk_event_get_device (event));

  if (widget)
    select_widget (iw, widget);
}
Example #14
0
static gboolean
on_widget_button_release (GtkWidget *widget,
			  GdkEventButton *event,
			  char *item_id)
{
  GdkDevice *device = gdk_event_get_device ((GdkEvent*) event);

  g_print ("%s received 'button-release' signal\n", item_id);

  if (device && strstr (item_id, "explicit"))
    {
      gdk_device_ungrab (device, event->time);
      g_print ("released pointer grab\n");
    }

  return TRUE;
}
Example #15
0
static gboolean
gtk_bubble_window_grab_broken (GtkWidget          *widget,
                               GdkEventGrabBroken *grab_broken)
{
  GtkBubbleWindow *window = GTK_BUBBLE_WINDOW (widget);
  GtkBubbleWindowPrivate *priv;
  GdkDevice *event_device;

  priv = window->priv;
  event_device = gdk_event_get_device ((GdkEvent *) grab_broken);

  if (event_device == priv->device ||
      event_device == gdk_device_get_associated_device (priv->device))
    _gtk_bubble_window_ungrab (window);

  return FALSE;
}
Example #16
0
static gboolean
overlay_enter_notify_cb (GtkWidget        *parent,
                         GdkEventCrossing *event,
                         gpointer          user_data)
{
    GtkWidget *widget = user_data;
    CheckPointerData *data;
    gint y_pos;

    NautilusFloatingBar *self = NAUTILUS_FLOATING_BAR (widget);

    if (self->hover_timeout_id != 0)
    {
        g_source_remove (self->hover_timeout_id);
    }

    if (event->window != gtk_widget_get_window (widget))
    {
        return GDK_EVENT_PROPAGATE;
    }

    if (NAUTILUS_FLOATING_BAR (widget)->is_interactive)
    {
        return GDK_EVENT_PROPAGATE;
    }

    gdk_window_get_position (gtk_widget_get_window (widget), NULL, &y_pos);

    data = g_slice_new (CheckPointerData);
    data->overlay = parent;
    data->floating_bar = widget;
    data->device = gdk_event_get_device ((GdkEvent *) event);
    data->y_down_limit = y_pos;
    data->y_upper_limit = y_pos + gtk_widget_get_allocated_height (widget);

    self->hover_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, HOVER_HIDE_TIMEOUT_INTERVAL,
                                                 check_pointer_timeout, data,
                                                 check_pointer_data_free);

    g_source_set_name_by_id (self->hover_timeout_id, "[nautilus-floating-bar] overlay_enter_notify_cb");

    return GDK_EVENT_STOP;
}
Example #17
0
static void gstroke_cancel(GdkEvent *event)
{
	last_mouse_position.invalid = TRUE;

	if (timer_id > 0)
	    g_source_remove (timer_id);

	timer_id = 0;

	if( event != NULL )
		gdk_device_ungrab(gdk_event_get_device(event), event->button.time);

	if (gstroke_draw_strokes() && gstroke_disp != NULL) {
	    /* get rid of the invisible stroke window */
	    XUnmapWindow (gstroke_disp, gstroke_window);
	    XFlush (gstroke_disp);
	}

}
Example #18
0
static gboolean
on_widget_button_release (GtkWidget *widget,
			  GdkEventButton *event,
			  char *item_id)
{
  GdkDevice *device = gdk_event_get_device ((GdkEvent*) event);

  g_print ("%s received 'button-release' signal\n", item_id);

  if (device && strstr (item_id, "explicit"))
    {
#if GTK_CHECK_VERSION(3,20,0)
      gdk_seat_ungrab (gdk_device_get_seat (device));
#else
      gdk_device_ungrab (device, event->time);
#endif
      g_print ("released pointer grab\n");
    }

  return TRUE;
}
Example #19
0
static void
handle_focus_change (GdkEventCrossing *event)
{
  GdkToplevelX11 *toplevel;
  GdkX11Screen *x11_screen;
  gboolean focus_in, had_focus;

  toplevel = _gdk_x11_window_get_toplevel (event->window);
  x11_screen = GDK_X11_SCREEN (gdk_window_get_screen (event->window));
  focus_in = (event->type == GDK_ENTER_NOTIFY);

  if (x11_screen->wmspec_check_window)
    return;

  if (!toplevel || event->detail == GDK_NOTIFY_INFERIOR)
    return;

  toplevel->has_pointer = focus_in;

  if (!event->focus || toplevel->has_focus_window)
    return;

  had_focus = HAS_FOCUS (toplevel);
  toplevel->has_pointer_focus = focus_in;

  if (HAS_FOCUS (toplevel) != had_focus)
    {
      GdkEvent *focus_event;

      focus_event = gdk_event_new (GDK_FOCUS_CHANGE);
      focus_event->focus_change.window = g_object_ref (event->window);
      focus_event->focus_change.send_event = FALSE;
      focus_event->focus_change.in = focus_in;
      gdk_event_set_device (focus_event, gdk_event_get_device ((GdkEvent *) event));

      gdk_event_put (focus_event);
      gdk_event_free (focus_event);
    }
}
static gboolean
password_dialog_ungrab_keyboard (GtkWidget *widget,
    GdkEvent *event,
    gpointer user_data)
{
  EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (user_data)->priv;

  if (priv->grabbing)
    {
      GdkDevice *device = gdk_event_get_device (event);

      if (device != NULL)
        {
          gdk_device_ungrab (device, gdk_event_get_time (event));
          priv->grabbing = FALSE;
        }
      else
        DEBUG ("Could not get the event device!");
    }

  return FALSE;
}
Example #21
0
///参照gtk+3.0中的gtk_widget_get_pointer写的
inline static void
gtk_widget_get_mouse_position(GtkWidget *widget,GdkEvent *event,gint *x,gint *y)
{
    GdkDevice *dev = NULL;
    if (x)
        *x = -1;
    if (y)
        *y = -1;
    if(event)
    {
        dev = gdk_event_get_device(event);
    }
    if(dev == NULL)
    {
        dev = gdk_device_manager_get_client_pointer (
                                        gdk_display_get_device_manager (
                                          gtk_widget_get_display (widget)));
    }

    if (gtk_widget_get_realized (widget))
    {
        gdk_window_get_device_position (gtk_widget_get_window(widget),
                                      dev,
                                      x, y, NULL);

        if (!gtk_widget_get_has_window (widget))
        {
            GtkAllocation alc = {0};
            gtk_widget_get_allocation(widget,&alc);
            if (x)
                *x -= alc.x;
            if (y)
                *y -= alc.y;
        }
    }
}
Example #22
0
//!
//! @brief To be written
//!
G_MODULE_EXPORT gint 
gw_kanjipadwindow_drawingarea_motion_event_cb (GtkWidget *widget, GdkEventMotion *event, gpointer data)
{
    //Declarations
    GwKanjipadWindow *window;
    GwKanjipadWindowPrivate *priv;
    gint x,y;
    GdkModifierType state;
    GdkRectangle rect;
    GdkPoint *point;
    int xmin, ymin, xmax, ymax;
    GdkPoint *old;
    cairo_t *cr;

    window = GW_KANJIPADWINDOW (gtk_widget_get_ancestor (GTK_WIDGET (data), GW_TYPE_KANJIPADWINDOW));
    if (window == NULL) return FALSE;
    priv = window->priv;

    if (event->is_hint)
    {
      gdk_window_get_device_position (
        gtk_widget_get_window (GTK_WIDGET (widget)),
        gdk_event_get_device ((GdkEvent*) event),
        &x, 
        &y, 
        &state
      );
    }
    else
    {
      x = event->x;
      y = event->y;
      state = event->state;
    }

    if (priv->instroke == TRUE && (state & GDK_BUTTON1_MASK))
    {
      old = (GdkPoint*) g_list_last (priv->curstroke)->data;

      //extend line
      cr = cairo_create(priv->surface);
      cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
      cairo_set_line_width (cr, 2.0 );
      cairo_move_to (cr, old->x,  old->y);
      cairo_line_to (cr, x, y);
      cairo_stroke (cr);
      cairo_destroy(cr);

      if (old->x < x) { xmin = old->x; xmax = x; }
      else            { xmin = x;      xmax = old->x; }

      if (old->y < y) { ymin = old->y; ymax = y; }
      else            { ymin = y;      ymax = old->y; }

      rect.x = xmin - 1 - 3; 
      rect.y = ymin = 1 - 3;
      rect.width  = xmax - xmin + 2 + 3;
      rect.height = ymax - ymin + 2 + 3;
      gdk_window_invalidate_rect (gtk_widget_get_window (widget), &rect, FALSE);

      point = g_new (GdkPoint, 1);
      point->x = x;
      point->y = y;
      priv->curstroke = g_list_append (priv->curstroke, point);

      gtk_widget_queue_draw (GTK_WIDGET (priv->drawingarea));
    }

    return TRUE;
}
/* This shots when the pointer is moving. */
G_MODULE_EXPORT gboolean
on_motion_notify   (GtkWidget       *win,
                    GdkEventMotion  *ev,
                    gpointer         user_data)
{
  AnnotateData *data = (AnnotateData *) user_data;
  GdkDevice *master = gdk_event_get_device ( (GdkEvent *) ev);
  GdkDevice *slave = gdk_event_get_source_device ( (GdkEvent *) ev);
  
  /* Get the data for this device. */
  AnnotateDeviceData *masterdata= g_hash_table_lookup (data->devdatatable, master);
  AnnotateDeviceData *slavedata = g_hash_table_lookup (data->devdatatable, slave);

   if (data->cur_context == data->default_filler)
    {
      return FALSE;
    }
    
  if (ev->state != masterdata->state ||
      ev->state != slavedata->state  ||
      masterdata->lastslave != slave)
    {
       annotate_select_tool (data, master, slave, ev->state);
    }

  gdouble selected_width = 0.0;
  gdouble pressure = 1.0; 

  if (!data->is_grabbed)
    {
      return FALSE;
    }

  if (!ev)
    {
      g_printerr ("Device '%s': Invalid event; I ungrab all\n",
                  gdk_device_get_name (master));
      annotate_release_grab ();
      return FALSE;
    }

  if (data->debug)
    {
      g_printerr ("Device '%s': Move at (x,y)= (%f : %f)\n",
                  gdk_device_get_name (master),
                  ev->x,
                  ev->y);
    }
  
#ifdef _WIN32
  if (inside_bar_window (ev->x_root, ev->y_root))
    {

      if (data->debug)
        {
          g_printerr ("Device '%s': Move on the bar then ungrab\n",
                       gdk_device_get_name (master));
        }

      /* The point is inside the ardesia bar then ungrab. */
      annotate_release_grab ();
      return FALSE;
    }
#endif

  annotate_unhide_cursor ();
  
  /* Only the first 5 buttons allowed. */
  if(!(ev->state & (GDK_BUTTON1_MASK|
                    GDK_BUTTON2_MASK|
                    GDK_BUTTON3_MASK|
                    GDK_BUTTON4_MASK|
                    GDK_BUTTON5_MASK)))
    {
      return TRUE;
    }

  initialize_annotation_cairo_context (data);

  annotate_configure_pen_options (data);
  
  if (data->cur_context->type != ANNOTATE_ERASER)
    {
      pressure = get_pressure ( (GdkEvent *) ev);

      if (pressure <= 0)
        {
          return FALSE;
        }

      /* If the point is already selected and higher pressure then print else jump it. */
      if (masterdata->coord_list)
        {
          AnnotatePoint *last_point = (AnnotatePoint *) g_slist_nth_data (masterdata->coord_list, 0);
          gdouble tollerance = annotate_get_thickness ();

          if (get_distance (last_point->x, last_point->y, ev->x, ev->y)<tollerance)
            {
              /* Seems that you are uprising the pen. */
              if (pressure <= last_point->pressure)
                {
                  /* Jump the point you are uprising the hand. */
                  return FALSE;
                }
              else // pressure >= last_point->pressure
                {
                  /* Seems that you are pressing the pen more. */
                  annotate_modify_color (masterdata, data, pressure);
                  annotate_draw_line (masterdata, ev->x, ev->y, TRUE);
                  /* Store the new pressure without allocate a new coordinate. */
                  last_point->pressure = pressure;
                  return TRUE;
                }
            }
          annotate_modify_color (masterdata, data, pressure);
        }
    }
    
  annotate_draw_line (masterdata, ev->x, ev->y, TRUE);
  annotate_coord_list_prepend (masterdata, ev->x, ev->y, selected_width, pressure);

  return TRUE;
}
Example #24
0
/**
 * clutter_gdk_handle_event:
 * @event: a #GdkEvent
 *
 * This function processes a single GDK event; it can be used to hook
 * into external event processing
 *
 * Return value: #GdkFilterReturn. %GDK_FILTER_REMOVE indicates that
 *  Clutter has internally handled the event and the caller should do
 *  no further processing. %GDK_FILTER_CONTINUE indicates that Clutter
 *  is either not interested in the event, or has used the event to
 *  update internal state without taking any exclusive action.
 *  %GDK_FILTER_TRANSLATE will not occur.
 *
 */
GdkFilterReturn
clutter_gdk_handle_event (GdkEvent *gdk_event)
{
  ClutterDeviceManager *device_manager;
  ClutterBackendGdk *backend_gdk;
  ClutterBackend *backend;
  ClutterStage *stage = NULL;
  ClutterEvent *event = NULL;
  gint spin = 0;
  GdkFilterReturn result = GDK_FILTER_CONTINUE;
  ClutterInputDevice *device, *source_device;
  GdkDevice *gdk_device;

  backend = clutter_get_default_backend ();
  if (!CLUTTER_IS_BACKEND_GDK (backend))
    return GDK_FILTER_CONTINUE;

  if (gdk_event->any.window == NULL)
    return GDK_FILTER_CONTINUE;

  device_manager = clutter_device_manager_get_default ();
  if (G_UNLIKELY (device_manager == NULL))
    return GDK_FILTER_CONTINUE;

  backend_gdk = CLUTTER_BACKEND_GDK (backend);
  stage = clutter_gdk_get_stage_from_window (gdk_event->any.window);

  gdk_device = gdk_event_get_device (gdk_event);
  if (gdk_device != NULL)
    device = _clutter_device_manager_gdk_lookup_device (device_manager,
                                                        gdk_device);
  else
    device = NULL;

  gdk_device = gdk_event_get_source_device (gdk_event);
  if (gdk_device != NULL)
    source_device = _clutter_device_manager_gdk_lookup_device (device_manager,
                                                               gdk_device);
  else
    source_device = NULL;

  if (stage == NULL)
    return GDK_FILTER_CONTINUE;

  _clutter_threads_acquire_lock ();

  switch (gdk_event->type)
    {
    case GDK_DELETE:
      event = clutter_event_new (CLUTTER_DELETE);
      break;

    case GDK_DESTROY:
      event = clutter_event_new (CLUTTER_DESTROY_NOTIFY);
      break;

    case GDK_EXPOSE:
      {
        ClutterPaintVolume clip;
        ClutterVertex origin;

        CLUTTER_NOTE (EVENT, "Expose for stage '%s' [%p] { %d, %d - %d x %d }",
                      _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage)),
                      stage,
                      gdk_event->expose.area.x,
                      gdk_event->expose.area.y,
                      gdk_event->expose.area.width,
                      gdk_event->expose.area.height);

        origin.x = gdk_event->expose.area.x;
        origin.y = gdk_event->expose.area.y;
        origin.z = 0;

        _clutter_paint_volume_init_static (&clip, CLUTTER_ACTOR (stage));

        clutter_paint_volume_set_origin (&clip, &origin);
        clutter_paint_volume_set_width (&clip, gdk_event->expose.area.width);
        clutter_paint_volume_set_height (&clip, gdk_event->expose.area.height);

        _clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), 0, &clip);

        clutter_paint_volume_free (&clip);
      }
      break;

    case GDK_DAMAGE:
      /* This is handled by cogl */
      break;

    case GDK_MOTION_NOTIFY:
      event = clutter_event_new (CLUTTER_MOTION);
      event->motion.time = gdk_event->motion.time;
      event->motion.x = gdk_event->motion.x;
      event->motion.y = gdk_event->motion.y;
      event->motion.axes = NULL;
      /* It's all X in the end, right? */
      event->motion.modifier_state = gdk_event->motion.state;
      clutter_event_set_device (event, device);
      clutter_event_set_source_device (event, source_device);
      CLUTTER_NOTE (EVENT, "Motion notifiy [%.2f, %.2f]",
                    event->motion.x,
                    event->motion.y);
      break;

    case GDK_BUTTON_PRESS:
    case GDK_BUTTON_RELEASE:
      event = clutter_event_new (gdk_event->type == GDK_BUTTON_PRESS ?
                                 CLUTTER_BUTTON_PRESS :
                                 CLUTTER_BUTTON_RELEASE);
      event->button.time = gdk_event->button.time;
      event->button.x = gdk_event->button.x;
      event->button.y = gdk_event->button.y;
      event->button.axes = NULL;
      event->button.modifier_state = gdk_event->button.state;
      event->button.button = gdk_event->button.button;
      event->button.click_count = 1;
      clutter_event_set_device (event, device);
      clutter_event_set_source_device (event, source_device);
      CLUTTER_NOTE (EVENT, "Button %d %s [%.2f, %.2f]",
                    event->button.button,
                    event->type == CLUTTER_BUTTON_PRESS ? "press" : "release",
                    event->button.x,
                    event->button.y);
      break;

    case GDK_2BUTTON_PRESS:
    case GDK_3BUTTON_PRESS:
      /* these are handled by clutter-main.c updating click_count */
      break;

    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      event = clutter_event_new (gdk_event->type == GDK_KEY_PRESS ?
                                 CLUTTER_KEY_PRESS :
                                 CLUTTER_KEY_RELEASE);
      event->key.time = gdk_event->key.time;
      event->key.modifier_state = gdk_event->key.state;
      event->key.keyval = gdk_event->key.keyval;
      event->key.hardware_keycode = gdk_event->key.hardware_keycode;
      event->key.unicode_value = g_utf8_get_char (gdk_event->key.string);
      clutter_event_set_device (event, device);
      clutter_event_set_source_device (event, source_device);
      CLUTTER_NOTE (EVENT, "Key %d %s",
                    event->key.keyval,
                    event->type == CLUTTER_KEY_PRESS ? "press" : "release");
      break;

    case GDK_ENTER_NOTIFY:
    case GDK_LEAVE_NOTIFY:
      event = clutter_event_new (gdk_event->type == GDK_ENTER_NOTIFY ?
                                 CLUTTER_ENTER :
                                 CLUTTER_LEAVE);
      event->crossing.source = CLUTTER_ACTOR (stage);
      event->crossing.time = gdk_event_get_time (gdk_event);
      event->crossing.x = gdk_event->crossing.x;
      event->crossing.y = gdk_event->crossing.y;

      /* XXX: no better fallback here? */
      clutter_event_set_device (event, device);
      clutter_event_set_source_device (event, source_device);
      if (gdk_event->type == GDK_ENTER_NOTIFY)
        _clutter_input_device_set_stage (clutter_event_get_device (event), stage);
      else
        _clutter_input_device_set_stage (clutter_event_get_device (event), NULL);
      CLUTTER_NOTE (EVENT, "Crossing %s [%.2f, %.2f]",
                    event->type == CLUTTER_ENTER ? "enter" : "leave",
                    event->crossing.x,
                    event->crossing.y);
      break;

    case GDK_FOCUS_CHANGE:
      if (gdk_event->focus_change.in)
        _clutter_stage_update_state (stage, 0, CLUTTER_STAGE_STATE_ACTIVATED);
      else
        _clutter_stage_update_state (stage, CLUTTER_STAGE_STATE_ACTIVATED, 0);
      break;

    case GDK_CONFIGURE:
      {
        gfloat w, h;

        clutter_actor_get_size (CLUTTER_ACTOR (stage), &w, &h);

        if (w != gdk_event->configure.width ||
            h != gdk_event->configure.height)
          {
            clutter_actor_set_size (CLUTTER_ACTOR (stage),
                                    gdk_event->configure.width,
                                    gdk_event->configure.height);
          }
      }
      break;

    case GDK_SCROLL:
      event = clutter_event_new (CLUTTER_SCROLL);
      event->scroll.time = gdk_event->scroll.time;
      event->scroll.x = gdk_event->scroll.x;
      event->scroll.y = gdk_event->scroll.y;
      event->scroll.modifier_state = gdk_event->scroll.state;
      event->scroll.axes = NULL;
      /* XXX: must keep ClutterScrollDirection compatible with GdkScrollDirection */
      event->scroll.direction = (ClutterScrollDirection) gdk_event->scroll.direction;
      clutter_event_set_device (event, device);
      clutter_event_set_source_device (event, source_device);
      clutter_event_set_scroll_delta (event,
                                      gdk_event->scroll.delta_x,
                                      gdk_event->scroll.delta_y);
      break;

    case GDK_WINDOW_STATE:
      if (gdk_event->window_state.changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
        {
          gboolean is_fullscreen;

          is_fullscreen = (gdk_event->window_state.new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
          if (is_fullscreen)
            _clutter_stage_update_state (stage, 0, CLUTTER_STAGE_STATE_FULLSCREEN);
          else
            _clutter_stage_update_state (stage, CLUTTER_STAGE_STATE_FULLSCREEN, 0);
        }
      break;

    case GDK_SETTING:
      _clutter_backend_gdk_update_setting (backend_gdk, gdk_event->setting.name);
      break;

    default:
      break;
    }

  if (event != NULL)
    {
      event->any.stage = stage;

      if (gdk_event->any.send_event)
	event->any.flags = CLUTTER_EVENT_FLAG_SYNTHETIC;

      _clutter_event_push (event, FALSE);

      spin = 1;

      CLUTTER_NOTE (EVENT, "Translated one event from Gdk");

      /* handle also synthetic enter/leave events */
      if (event->type == CLUTTER_MOTION)
	spin += 2;

      while (spin > 0 && (event = clutter_event_get ()))
	{
	  /* forward the event into clutter for emission etc. */
	  clutter_do_event (event);
	  clutter_event_free (event);
	  --spin;
	}

      result = GDK_FILTER_REMOVE;
    }

  _clutter_threads_release_lock ();

  return result;
}
Example #25
0
static void
gimp_pick_button_pick (GimpPickButton *button,
                       GdkEvent       *event)
{
  GdkScreen        *screen = gdk_event_get_screen (event);
  GimpColorProfile *monitor_profile;
  GdkMonitor       *monitor;
  GimpRGB           rgb;
  gint              x_root;
  gint              y_root;
  gdouble           x_win;
  gdouble           y_win;

  gdk_window_get_origin (gdk_event_get_window (event), &x_root, &y_root);
  gdk_event_get_coords (event, &x_win, &y_win);
  x_root += x_win;
  y_root += y_win;

#ifdef G_OS_WIN32

  {
    HDC      hdc;
    RECT     rect;
    COLORREF win32_color;

    /* For MS Windows, use native GDI functions to get the pixel, as
     * cairo does not handle the case where you have multiple monitors
     * with a monitor on the left or above the primary monitor.  That
     * scenario create a cairo primary surface with negative extent,
     * which is not handled properly (bug 740634).
     */

    hdc = GetDC (HWND_DESKTOP);
    GetClipBox (hdc, &rect);
    win32_color = GetPixel (hdc, x_root + rect.left, y_root + rect.top);
    ReleaseDC (HWND_DESKTOP, hdc);

    gimp_rgba_set_uchar (&rgb,
                         GetRValue (win32_color),
                         GetGValue (win32_color),
                         GetBValue (win32_color),
                         255);
  }

#else

  {
    GdkWindow       *window;
    gint             x_window;
    gint             y_window;
    cairo_surface_t *image;
    cairo_t         *cr;
    guchar          *data;
    guchar           color[3];

    /* we try to pick from the local window under the cursor, and fall
     * back to picking from the root window if this fails (i.e., if
     * the cursor is not under a local window).  on wayland, picking
     * from the root window is not supported, so this at least allows
     * us to pick from local windows.  see bug #780375.
     */
    window = gdk_device_get_window_at_position (gdk_event_get_device (event),
                                                &x_window, &y_window);
    if (! window)
      {
        window   = gdk_screen_get_root_window (screen);
        x_window = x_root;
        y_window = y_root;
      }

    image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 1, 1);

    cr = cairo_create (image);

    gdk_cairo_set_source_window (cr, window, -x_window, -y_window);
    cairo_paint (cr);

    cairo_destroy (cr);

    data = cairo_image_surface_get_data (image);
    GIMP_CAIRO_RGB24_GET_PIXEL (data, color[0], color[1], color[2]);

    cairo_surface_destroy (image);

    gimp_rgba_set_uchar (&rgb, color[0], color[1], color[2], 255);
  }

#endif

  monitor = gdk_display_get_monitor_at_point (gdk_screen_get_display (screen),
                                              x_root, y_root);
  monitor_profile = gimp_monitor_get_color_profile (monitor);

  if (monitor_profile)
    {
      GimpColorProfile        *srgb_profile;
      GimpColorTransform      *transform;
      const Babl              *format;
      GimpColorTransformFlags  flags = 0;

      format = babl_format ("R'G'B'A double");

      flags |= GIMP_COLOR_TRANSFORM_FLAGS_NOOPTIMIZE;
      flags |= GIMP_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION;

      srgb_profile = gimp_color_profile_new_rgb_srgb ();
      transform = gimp_color_transform_new (monitor_profile, format,
                                            srgb_profile,    format,
                                            GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
                                            flags);
      g_object_unref (srgb_profile);

      if (transform)
        {
          gimp_color_transform_process_pixels (transform,
                                               format, &rgb,
                                               format, &rgb,
                                               1);
          gimp_rgb_clamp (&rgb);

          g_object_unref (transform);
        }
    }

  g_signal_emit_by_name (button, "color-picked", &rgb);
}
static gboolean
gstyle_eyedropper_key_pressed_cb (GstyleEyedropper *self,
                                  GdkEventKey      *event,
                                  GtkWindow        *window)
{
  GdkSeat *seat;
  GdkDevice *pointer;
  GdkDevice *keyboard;
  gint x, y;
  gint dx = 0;
  gint dy = 0;
  gint state;

  g_assert (GSTYLE_IS_EYEDROPPER (self));
  g_assert (event != NULL);
  g_assert (GTK_IS_WINDOW (window));

  state = (event->state & gtk_accelerator_get_default_mod_mask () & GDK_MOD1_MASK);
  switch (event->keyval)
    {
    case GDK_KEY_Escape:
      release_grab (self);
      return GDK_EVENT_STOP;
      break;

    case GDK_KEY_Up:
    case GDK_KEY_KP_Up:
      dy = (state == GDK_MOD1_MASK) ? -CURSOR_ALT_STEP : -1;
      break;

    case GDK_KEY_Down:
    case GDK_KEY_KP_Down:
      dy = (state == GDK_MOD1_MASK) ? CURSOR_ALT_STEP : 1;
      break;

    case GDK_KEY_Left:
    case GDK_KEY_KP_Left:
      dx = (state == GDK_MOD1_MASK) ? -CURSOR_ALT_STEP : -1;
      break;

    case GDK_KEY_Right:
    case GDK_KEY_KP_Right:
      dx = (state == GDK_MOD1_MASK) ? CURSOR_ALT_STEP : 1;
      break;

    case GDK_KEY_Page_Up:
    case GDK_KEY_KP_Page_Up:
      increase_zoom_factor (self);
      break;

    case GDK_KEY_Page_Down:
    case GDK_KEY_KP_Page_Down:
      decrease_zoom_factor (self);
      break;

    default:
      return GDK_EVENT_PROPAGATE;
    }

  keyboard = gdk_event_get_device ((GdkEvent *)event);
  seat = gdk_device_get_seat (keyboard);
  pointer = gdk_seat_get_pointer (seat);
  gdk_device_get_position (pointer, NULL, &x, &y);
  gdk_device_warp (pointer, self->screen, x + dx, y + dy);

  return GDK_EVENT_STOP;
}
Example #27
0
static gint
process_event (GtkWidget *widget, GdkEvent *event, gpointer data G_GNUC_UNUSED)
{
  static GtkWidget *original_widget = NULL;
  static GdkCursor *cursor = NULL;

  switch (event->type) {
    case GDK_BUTTON_PRESS:
		if (event->button.button != gstroke_get_mouse_button()) {
			/* Similar to the bug below catch when any other button is
			 * clicked after the middle button is clicked (but possibly
			 * not released)
			 */
			gstroke_cancel(event);
			original_widget = NULL;
			break;
		}

      original_widget = widget; /* remeber the widget where
                                   the stroke started */

      gstroke_invisible_window_init (widget);

      record_stroke_segment (widget);

	  if (cursor == NULL)
		  cursor = gdk_cursor_new(GDK_PENCIL);

      gdk_device_grab(gdk_event_get_device(event),
                      gtk_widget_get_window(widget), GDK_OWNERSHIP_WINDOW,
                      FALSE, GDK_BUTTON_RELEASE_MASK, cursor,
                      event->button.time);
      timer_id = g_timeout_add (GSTROKE_TIMEOUT_DURATION,
				  gstroke_timeout, widget);
      return TRUE;

    case GDK_BUTTON_RELEASE:
      if ((event->button.button != gstroke_get_mouse_button())
	  || (original_widget == NULL)) {

		/* Nice bug when you hold down one button and press another. */
		/* We'll just cancel the gesture instead. */
		gstroke_cancel(event);
		original_widget = NULL;
		break;
	  }

      last_mouse_position.invalid = TRUE;
      original_widget = NULL;
      g_source_remove (timer_id);
      gdk_device_ungrab(gdk_event_get_device(event), event->button.time);
      timer_id = 0;

      {
	char result[GSTROKE_MAX_SEQUENCE];
	struct gstroke_metrics *metrics;

	metrics = (struct gstroke_metrics *)g_object_get_data(G_OBJECT (widget),
														  GSTROKE_METRICS);
		if (gstroke_draw_strokes()) {
			/* get rid of the invisible stroke window */
			XUnmapWindow (gstroke_disp, gstroke_window);
			XFlush (gstroke_disp);
		}

	_gstroke_canonical (result, metrics);
	gstroke_execute (widget, result);
      }
      return FALSE;

    default:
      break;
  }

  return FALSE;
}
/* This is called when the button is pushed. */
G_MODULE_EXPORT gboolean
on_button_press    (GtkWidget      *win,
                    GdkEventButton *ev,
                    gpointer        user_data)
{

  AnnotateData *data = (AnnotateData *) user_data;
  GdkDevice *master = gdk_event_get_device ( (GdkEvent *) ev);
  
  /* Get the data for this device. */
  AnnotateDeviceData *masterdata = g_hash_table_lookup (data->devdatatable, master);
  
  gdouble pressure = 1.0;
  
  if (data->cur_context == data->default_filler)
    {
      return FALSE;
    }
  
  if (!data->is_grabbed)
    {
      return FALSE;
    }
	
  if (!ev)
    {
      g_printerr ("Device '%s': Invalid event; I ungrab all\n",
                  gdk_device_get_name (master));
      annotate_release_grab ();
      return FALSE;
    }
	
  if (data->debug)
    {
      g_printerr ("Device '%s': Button %i Down at (x,y)= (%f : %f)\n",
                  gdk_device_get_name (master),
                  ev->button,
                  ev->x,
                  ev->y);
    }

#ifdef _WIN32
  if (inside_bar_window (ev->x_root, ev->y_root))
    {
      /* The point is inside the ardesia bar then ungrab. */
      annotate_release_grab ();
      return FALSE;
    }
#endif

  pressure = get_pressure ( (GdkEvent *) ev);

  if (pressure <= 0)
    {
      return FALSE;
    }
	
  annotate_unhide_cursor ();

  initialize_annotation_cairo_context (data);

  annotate_configure_pen_options (data);

  annotate_coord_dev_list_free (masterdata);
  annotate_draw_point (masterdata, ev->x, ev->y, pressure);

  annotate_coord_list_prepend (masterdata,
                               ev->x,
                               ev->y,
                               annotate_get_thickness (),
                               pressure);

  return TRUE;
}
/* This shots when the button is released. */
G_MODULE_EXPORT gboolean
on_button_release  (GtkWidget       *win,
                    GdkEventButton  *ev,
                    gpointer         user_data)
{
  AnnotateData *data = (AnnotateData *) user_data;
  
  GdkDevice *master = gdk_event_get_device ( (GdkEvent *) ev);
  
  /* Get the data for this device. */
  AnnotateDeviceData *masterdata= g_hash_table_lookup (data->devdatatable, master);
  
  guint lenght = g_slist_length (masterdata->coord_list);

  if (!data->is_grabbed)
    {
      return FALSE;
    }
	
  if (!ev)
    {
      g_printerr ("Device '%s': Invalid event; I ungrab all\n",
                  gdk_device_get_name (master));
      annotate_release_grab ();
      return FALSE;
    }

  if (data->debug)
    {
      g_printerr ("Device '%s': Button %i Up at (x,y)= (%.2f : %.2f)\n",
                  gdk_device_get_name (master),
                   ev->button, ev->x, ev->y);
    }

#ifdef _WIN32
  if (inside_bar_window (ev->x_root, ev->y_root))
    /* Point is in the ardesia bar. */
    {
      /* The last point was outside the bar then ungrab. */
      annotate_release_grab ();
      return FALSE;
    }
  if (data->old_paint_type == ANNOTATE_PEN)
    {
       annotate_select_pen ();
    }
#endif

  if (data->cur_context == data->default_filler)
    {
      annotate_fill (masterdata, data, ev->x, ev->y);
      return TRUE;
    }
    
  initialize_annotation_cairo_context (data);

  if (lenght > 2)
    {
      AnnotatePoint *first_point = (AnnotatePoint *) g_slist_nth_data (masterdata->coord_list, lenght-1);
      AnnotatePoint *last_point = (AnnotatePoint *) g_slist_nth_data (masterdata->coord_list, 0);

      gdouble distance = get_distance (ev->x, ev->y, first_point->x, first_point->y);

      /* This is the tolerance to force to close the path in a magnetic way. */
      gint score = 3;
      
      /* If is applied some handled drawing mode then the tool is more tollerant. */
      if ((data->rectify || data->roundify))
        {
          score = 6;
        }
        
      gdouble tollerance = annotate_get_thickness () * score;

      gdouble pressure = last_point->pressure;
      annotate_modify_color (masterdata, data, pressure);

      gboolean closed_path = FALSE;

      /* If the distance between two point lesser than tolerance they are the same point for me. */
      if (distance > tollerance)
        {
          /* Different point. */
          annotate_draw_line (masterdata, ev->x, ev->y, TRUE);
          annotate_coord_list_prepend (masterdata, ev->x, ev->y, annotate_get_thickness (), pressure);
        }
      else
        {
          /* Rounded to be the same point. */
          closed_path = TRUE; // this seems to be a closed path
          annotate_draw_line (masterdata, first_point->x, first_point->y, TRUE);
          annotate_coord_list_prepend (masterdata, first_point->x, first_point->y, annotate_get_thickness (), pressure);
        }

      if (data->cur_context->type != ANNOTATE_ERASER)
        {
          annotate_shape_recognize (masterdata, closed_path);

          /* If is selected an arrow type then I draw the arrow. */
          if (data->arrow)
            {
              /* Print arrow at the end of the path. */
              annotate_draw_arrow (masterdata, distance);
            }
        }
    }

  cairo_stroke (data->annotation_cairo_context);

  annotate_add_savepoint ();

  annotate_hide_cursor ();

  return TRUE;
}
void WebPopupMenuProxyGtk::showPopupMenu(const IntRect& rect, TextDirection, double /* pageScaleFactor */, const Vector<WebPopupItem>& items, const PlatformPopupMenuData&, int32_t selectedIndex)
{
    populatePopupMenu(items);
    gtk_menu_set_active(GTK_MENU(m_popup), selectedIndex);

    resetTypeAheadFindState();


    IntPoint menuPosition = convertWidgetPointToScreenPoint(m_webView, rect.location());
    menuPosition.move(0, rect.height());

    // This approach follows the one in gtkcombobox.c.
    GtkRequisition requisition;
    gtk_widget_set_size_request(m_popup, -1, -1);
    gtk_widget_get_preferred_size(m_popup, &requisition, nullptr);
    gtk_widget_set_size_request(m_popup, std::max(rect.width(), requisition.width), -1);

    if (int itemCount = items.size()) {
        GUniquePtr<GList> children(gtk_container_get_children(GTK_CONTAINER(m_popup)));
        int i;
        GList* child;
        for (i = 0, child = children.get(); i < itemCount; i++, child = g_list_next(child)) {
            if (i > selectedIndex)
                break;

            GtkWidget* item = GTK_WIDGET(child->data);
            GtkRequisition itemRequisition;
            gtk_widget_get_preferred_size(item, &itemRequisition, nullptr);
            menuPosition.setY(menuPosition.y() - itemRequisition.height);
        }
    } else {
        // Center vertically the empty popup in the combo box area.
        menuPosition.setY(menuPosition.y() - rect.height() / 2);
    }

    gulong unmapHandler = g_signal_connect(m_popup, "unmap", G_CALLBACK(menuUnmapped), this);

    const GdkEvent* event = m_client->currentlyProcessedMouseDownEvent() ? m_client->currentlyProcessedMouseDownEvent()->nativeEvent() : nullptr;
    gtk_menu_popup_for_device(GTK_MENU(m_popup), event ? gdk_event_get_device(event) : nullptr, nullptr, nullptr,
        [](GtkMenu*, gint* x, gint* y, gboolean* pushIn, gpointer userData) {
            // We can pass a pointer to the menuPosition local variable because the nested main loop ensures this is called in the function context.
            IntPoint* menuPosition = static_cast<IntPoint*>(userData);
            *x = menuPosition->x();
            *y = menuPosition->y();
            *pushIn = TRUE;
        }, &menuPosition, nullptr, event && event->type == GDK_BUTTON_PRESS ? event->button.button : 1,
        event ? gdk_event_get_time(event) : GDK_CURRENT_TIME);

    // Now that the menu has a position, schedule a resize to make sure it's resized to fit vertically in the work area.
    gtk_widget_queue_resize(m_popup);

    // PopupMenu can fail to open when there is no mouse grab.
    // Ensure WebCore does not go into some pesky state.
    if (!gtk_widget_get_visible(m_popup)) {
       m_client->failedToShowPopupMenu();
       return;
    }

    // WebPageProxy expects the menu to run in a nested run loop, since it invalidates the
    // menu right after calling WebPopupMenuProxy::showPopupMenu().
    m_runLoop = adoptGRef(g_main_loop_new(nullptr, FALSE));

// This is to suppress warnings about gdk_threads_leave and gdk_threads_enter.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
    gdk_threads_leave();
    g_main_loop_run(m_runLoop.get());
    gdk_threads_enter();
#pragma GCC diagnostic pop

    m_runLoop.clear();

    g_signal_handler_disconnect(m_popup, unmapHandler);

    if (!m_client)
        return;

    m_client->valueChangedForPopupMenu(this, m_activeItem);
}