static void go_combo_box_popup_hide_unconditional (GOComboBox *combo_box) { gboolean popup_info_destroyed = FALSE; GObject *pdc; g_return_if_fail (combo_box != NULL); g_return_if_fail (GO_IS_COMBO_BOX (combo_box)); gtk_widget_hide (combo_box->priv->toplevel); gtk_widget_hide (combo_box->priv->popup); if (combo_box->priv->torn_off) go_combo_set_tearoff_state (combo_box, FALSE); do_focus_change (combo_box->priv->toplevel, FALSE); gtk_grab_remove (combo_box->priv->toplevel); gdk_device_ungrab (gtk_get_current_event_device (), GDK_CURRENT_TIME); pdc = g_object_ref (combo_box->priv->popdown_container); g_signal_emit (combo_box, go_combo_box_signals [POP_DOWN_DONE], 0, pdc, &popup_info_destroyed); if (popup_info_destroyed){ gtk_container_remove ( GTK_CONTAINER (combo_box->priv->frame), combo_box->priv->popdown_container); combo_box->priv->popdown_container = NULL; } g_object_unref (pdc); set_arrow_state (combo_box, FALSE); }
static void grab_window_toggled (GtkToggleButton *button, GtkWidget *widget) { GdkDevice *device = gtk_get_current_event_device (); if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD) device = gdk_device_get_associated_device (device); if (gtk_toggle_button_get_active (button)) { int status; status = gdk_device_grab (device, gtk_widget_get_window (widget), GDK_OWNERSHIP_NONE, FALSE, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, NULL, GDK_CURRENT_TIME); if (status != GDK_GRAB_SUCCESS) g_warning ("Could not grab keyboard! (%s)", grab_string (status)); } else { gdk_device_ungrab (device, GDK_CURRENT_TIME); } }
static void nemo_query_editor_grab_focus (GtkWidget *widget) { NemoQueryEditor *editor = NEMO_QUERY_EDITOR (widget); if (gtk_widget_get_visible (widget)) { entry_focus_hack (editor->details->entry, gtk_get_current_event_device ()); } }
/* Asks the user to click on a window, then waits for them click * the mouse. When the mouse is released, returns the toplevel * window under the pointer, or NULL, if there is none. */ static GtkWidget * query_for_toplevel (GdkScreen *screen, const char *prompt) { GdkDisplay *display = gdk_screen_get_display (screen); GtkWidget *popup, *label, *frame; GdkCursor *cursor; GtkWidget *toplevel = NULL; popup = gtk_window_new (GTK_WINDOW_POPUP); gtk_window_set_screen (GTK_WINDOW (popup), screen); gtk_window_set_modal (GTK_WINDOW (popup), TRUE); gtk_window_set_position (GTK_WINDOW (popup), GTK_WIN_POS_CENTER); frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); gtk_container_add (GTK_CONTAINER (popup), frame); label = gtk_label_new (prompt); g_object_set (label, "margin", 10, NULL); gtk_container_add (GTK_CONTAINER (frame), label); gtk_widget_show_all (popup); cursor = gdk_cursor_new_from_name (display, "crosshair"); if (gdk_device_grab (gtk_get_current_event_device (), gtk_widget_get_window (popup), GDK_OWNERSHIP_NONE, FALSE, GDK_BUTTON_RELEASE_MASK, cursor, GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS) { gboolean clicked = FALSE; g_signal_connect (popup, "button-release-event", G_CALLBACK (button_release_event_cb), &clicked); /* Process events until clicked is set by button_release_event_cb. * We pass in may_block=TRUE since we want to wait if there * are no events currently. */ while (!clicked) g_main_context_iteration (NULL, TRUE); toplevel = find_toplevel_at_pointer (gdk_screen_get_display (screen)); if (toplevel == popup) toplevel = NULL; } g_object_unref (cursor); gtk_widget_destroy (popup); gdk_flush (); /* Really release the grab */ return toplevel; }
void _gtk_tooltip_focus_in (GtkWidget *widget) { gint x, y; gboolean return_value = FALSE; GdkDisplay *display; GtkTooltip *tooltip; GdkDevice *device; /* Get current tooltip for this display */ display = gtk_widget_get_display (widget); tooltip = g_object_get_data (G_OBJECT (display), "gdk-display-current-tooltip"); /* Check if keyboard mode is enabled at this moment */ if (!tooltip || !tooltip->keyboard_mode_enabled) return; device = gtk_get_current_event_device (); if (device && gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) device = gdk_device_get_associated_device (device); /* This function should be called by either a focus in event, * or a key binding. In either case there should be a device. */ if (!device) return; if (tooltip->keyboard_widget) g_object_unref (tooltip->keyboard_widget); tooltip->keyboard_widget = g_object_ref (widget); gdk_window_get_device_position (gtk_widget_get_window (widget), device, &x, &y, NULL); return_value = gtk_tooltip_run_requery (&widget, tooltip, &x, &y); if (!return_value) { gtk_tooltip_hide_tooltip (tooltip); return; } if (!tooltip->current_window) { if (gtk_widget_get_tooltip_window (widget)) tooltip->current_window = gtk_widget_get_tooltip_window (widget); else tooltip->current_window = GTK_WINDOW (GTK_TOOLTIP (tooltip)->window); } gtk_tooltip_show_tooltip (display); }
static void photos_searchbar_default_show (PhotosSearchbar *self) { PhotosSearchbarPrivate *priv = self->priv; GdkDevice *event_device; event_device = gtk_get_current_event_device (); gtk_revealer_set_reveal_child (GTK_REVEALER (self), TRUE); priv->in = TRUE; if (event_device != NULL) gd_entry_focus_hack (priv->search_entry, event_device); }
/** * go_combo_popup_tear_off * @combo: Combo box * @set_position: Set to position of popup shell if true * * Tear off the popup * * FIXME: * Gtk popup menus are toplevel windows, not dialogs. I think this is wrong, * and make the popups dialogs. But may be there should be a way to make * them toplevel. We can do this after creating: * GTK_WINDOW (tearoff)->type = GTK_WINDOW_TOPLEVEL; */ static void go_combo_popup_tear_off (GOComboBox *combo, gboolean set_position) { int x, y; if (!combo->priv->tearoff_window) { GtkWidget *tearoff; gchar const *title; /* FIXME: made this a toplevel, not a dialog ! */ tearoff = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_object_ref_sink (tearoff); combo->priv->tearoff_window = tearoff; gtk_widget_set_app_paintable (tearoff, TRUE); g_signal_connect (tearoff, "key_press_event", G_CALLBACK (cb_combo_keypress), combo); gtk_widget_realize (tearoff); title = go_combo_box_get_title (combo); if (title) gdk_window_set_title (gtk_widget_get_window (tearoff), title); gtk_window_set_transient_for (GTK_WINDOW (tearoff), GTK_WINDOW (gtk_widget_get_toplevel GTK_WIDGET (combo))); } if (gtk_widget_get_visible (combo->priv->popup)) { gtk_widget_hide (combo->priv->toplevel); gtk_grab_remove (combo->priv->toplevel); gdk_device_ungrab (gtk_get_current_event_device (), GDK_CURRENT_TIME); } go_combo_popup_reparent (combo->priv->popup, combo->priv->tearoff_window, FALSE); /* It may have got confused about size */ gtk_widget_queue_resize (GTK_WIDGET (combo->priv->popup)); if (set_position) { go_combo_box_get_pos (combo, &x, &y); gtk_window_move (GTK_WINDOW (combo->priv->tearoff_window), x, y); } gtk_widget_show (GTK_WIDGET (combo->priv->popup)); gtk_widget_show (combo->priv->tearoff_window); }
void gtk_popup_button_popup (GtkPopupButton *popup_button) { GdkDevice *device = gtk_get_current_event_device (); if (!device) { GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (popup_button)); GdkDeviceManager *device_manager = gdk_display_get_device_manager (display); GList *devices = gdk_device_manager_list_devices ( device_manager, GDK_DEVICE_TYPE_MASTER); device = devices->data; g_list_free (devices); } gtk_popup_button_popup_for_device (popup_button, device); }
static void on_pointer_press(GtkWidget *widget, GdkEventButton *event, gpointer data) { // Hide the volume scale hide_volume_scale(); // Find the pointer device, if possible GdkDevice *device = gtk_get_current_event_device(); if (device && gdk_device_get_source(device) == GDK_SOURCE_KEYBOARD) device = gdk_device_get_associated_device(device); if (!device) { g_printerr("Failed to find the pointer device\n"); return; } // Ungrab it gdk_device_ungrab(device, GDK_CURRENT_TIME); gdk_flush(); }
/* protected */ void go_combo_box_popup_display (GOComboBox *combo_box) { int x, y; g_return_if_fail (GO_COMBO_BOX (combo_box) != NULL); g_return_if_fail (combo_box->priv->popdown_container != NULL); if (combo_box->priv->torn_off) { /* To give the illusion that tearoff still displays the * popup, we copy the image in the popup window to the * background. Thus, it won't be blank after reparenting */ go_combo_tearoff_bg_copy (combo_box); /* We force an unrealize here so that we don't trigger * redrawing/ clearing code - we just want to reveal our * backing pixmap. */ go_combo_popup_reparent (combo_box->priv->popup, combo_box->priv->toplevel, TRUE); } go_combo_box_get_pos (combo_box, &x, &y); gtk_window_move (GTK_WINDOW (combo_box->priv->toplevel), x, y); gtk_widget_realize (combo_box->priv->popup); gtk_widget_show (combo_box->priv->popup); gtk_widget_realize (combo_box->priv->toplevel); gtk_widget_show (combo_box->priv->toplevel); gtk_widget_grab_focus (combo_box->priv->toplevel); do_focus_change (combo_box->priv->toplevel, TRUE); gtk_grab_add (combo_box->priv->toplevel); gdk_device_grab (gtk_get_current_event_device (), gtk_widget_get_window (combo_box->priv->toplevel), GDK_OWNERSHIP_APPLICATION, TRUE, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK, NULL, GDK_CURRENT_TIME); set_arrow_state (combo_box, TRUE); }
/** * Handles the 'activate' signal on the tray_icon, * usually opening the popup_window and grabbing pointer and keyboard. * * @param status_icon the object which received the signal * @param user_data user data set when the signal handler was connected */ void tray_icon_on_click(G_GNUC_UNUSED GtkStatusIcon *status_icon, G_GNUC_UNUSED gpointer user_data) { get_current_levels(); if (!gtk_widget_get_visible(GTK_WIDGET(popup_window))) { gtk_widget_show_now(popup_window); gtk_widget_grab_focus(vol_scale); #ifdef WITH_GTK3 GdkDevice *pointer_dev = gtk_get_current_event_device(); if (pointer_dev != NULL) { GdkDevice *keyboard_dev = gdk_device_get_associated_device(pointer_dev); if (gdk_device_grab(pointer_dev, gtk_widget_get_window(GTK_WIDGET(popup_window)), GDK_OWNERSHIP_NONE, TRUE, GDK_BUTTON_PRESS_MASK, NULL, GDK_CURRENT_TIME) != GDK_GRAB_SUCCESS) g_warning("Could not grab %s\n", gdk_device_get_name(pointer_dev)); if (keyboard_dev != NULL) { if (gdk_device_grab(keyboard_dev, gtk_widget_get_window(GTK_WIDGET(popup_window)), GDK_OWNERSHIP_NONE, TRUE, GDK_KEY_PRESS_MASK, NULL, GDK_CURRENT_TIME) != GDK_GRAB_SUCCESS) g_warning("Could not grab %s\n", gdk_device_get_name(keyboard_dev)); } } #else gdk_keyboard_grab(gtk_widget_get_window(popup_window), TRUE, GDK_CURRENT_TIME); gdk_pointer_grab(gtk_widget_get_window(popup_window), TRUE, GDK_BUTTON_PRESS_MASK, NULL, NULL, GDK_CURRENT_TIME); #endif } else { gtk_widget_hide(popup_window); } }
void show_volume_scale(GdkRectangle *rect_or_null) { // Actually show the volume scale do_show_volume_scale(rect_or_null); // Find the pointer device, if possible GdkDevice *device = gtk_get_current_event_device(); if (device && gdk_device_get_source(device) == GDK_SOURCE_KEYBOARD) device = gdk_device_get_associated_device(device); if (!device) { g_printerr("Failed to find the pointer device\n"); return; } // Grab it so we can hide the scale when the user clicks outside it g_signal_connect_after(G_OBJECT(window), "button_press_event", G_CALLBACK(on_pointer_press), NULL); gdk_device_grab(device, gtk_widget_get_window(window), GDK_OWNERSHIP_NONE, TRUE, GDK_BUTTON_PRESS_MASK, NULL, GDK_CURRENT_TIME); gdk_flush(); }
/** * Hides the volume popup_window, connected via the signals * button-press-event, key-press-event and grab-broken-event. * * @param widget the object which received the signal * @param event the GdkEventButton which triggered the signal * @param user_data user data set when the signal handler was connected * @return TRUE to stop other handlers from being invoked for the evend, * FALSE to propagate the event further */ gboolean hide_me(G_GNUC_UNUSED GtkWidget *widget, GdkEvent *event, G_GNUC_UNUSED gpointer user_data) { #ifdef WITH_GTK3 GdkDevice *device = gtk_get_current_event_device(); #endif gint x, y; switch (event->type) { /* If a click happens outside of the popup, hide it */ case GDK_BUTTON_PRESS: if ( #ifdef WITH_GTK3 !gdk_device_get_window_at_position(device, &x, &y) #else !gdk_window_at_pointer(&x, &y) #endif ) gtk_widget_hide(popup_window); break; /* If 'Esc' is pressed, hide popup */ case GDK_KEY_PRESS: if (event->key.keyval == GDK_KEY_Escape) { gtk_widget_hide(popup_window); } break; /* Broken grab, hide popup */ case GDK_GRAB_BROKEN: gtk_widget_hide(popup_window); break; /* Unhandle event, do nothing */ default: break; } return FALSE; }
/* Finds the toplevel window under the mouse pointer, if any. */ static GtkWidget * find_toplevel_at_pointer (GdkDisplay *display) { GdkWindow *pointer_window; GtkWidget *widget = NULL; pointer_window = gdk_device_get_window_at_position (gtk_get_current_event_device (), NULL, NULL); /* The user data field of a GdkWindow is used to store a pointer * to the widget that created it. */ if (pointer_window) { gpointer widget_ptr; gdk_window_get_user_data (pointer_window, &widget_ptr); widget = widget_ptr; } return widget ? gtk_widget_get_toplevel (widget) : NULL; }
static void grab_devices(GtkWidget *window) { GdkGrabStatus status; GdkDevice *device; /* Grab the current event device */ device = gtk_get_current_event_device(); if (device == NULL) { WARN("Couldn't get current device"); return; } /* Grab every seat capabilities */ status = gdk_seat_grab(gdk_device_get_seat(device), gtk_widget_get_window(window), GDK_SEAT_CAPABILITY_ALL, TRUE, NULL, NULL, NULL, NULL); if (status != GDK_GRAB_SUCCESS) WARN("Could not grab %s", gdk_device_get_name(device)); }
static void grab_devices(GtkWidget *window) { GdkDevice *pointer_dev; GdkDevice *keyboard_dev; GdkGrabStatus status; /* Grab the mouse */ pointer_dev = gtk_get_current_event_device(); if (pointer_dev == NULL) { WARN("Couldn't get current device"); return; } status = gdk_device_grab(pointer_dev, gtk_widget_get_window(window), GDK_OWNERSHIP_NONE, TRUE, GDK_BUTTON_PRESS_MASK, NULL, GDK_CURRENT_TIME); if (status != GDK_GRAB_SUCCESS) WARN("Could not grab %s", gdk_device_get_name(pointer_dev)); /* Grab the keyboard */ keyboard_dev = gdk_device_get_associated_device(pointer_dev); if (keyboard_dev == NULL) { WARN("Couldn't get associated device"); return; } status = gdk_device_grab(keyboard_dev, gtk_widget_get_window(window), GDK_OWNERSHIP_NONE, TRUE, GDK_KEY_PRESS_MASK, NULL, GDK_CURRENT_TIME); if (status != GDK_GRAB_SUCCESS) WARN("Could not grab %s", gdk_device_get_name(keyboard_dev)); }
/** * Handles 'button-press-event', 'key-press-event' and 'grab-broken-event' signals, * on the GtkWindow. Used to hide the volume popup window. * * @param widget the object which received the signal. * @param event the GdkEvent which triggered this signal. * @param window user data set when the signal handler was connected. * @return TRUE to stop other handlers from being invoked for the event. * FALSE to propagate the event further. */ gboolean on_popup_window_event(G_GNUC_UNUSED GtkWidget *widget, GdkEvent *event, PopupWindow *window) { switch (event->type) { /* If a click happens outside of the popup, hide it */ case GDK_BUTTON_PRESS: { gint x, y; #ifdef WITH_GTK3 GdkDevice *device = gtk_get_current_event_device(); if (!gdk_device_get_window_at_position(device, &x, &y)) #else if (!gdk_window_at_pointer(&x, &y)) #endif popup_window_hide(window); break; } /* If 'Esc' is pressed, hide popup */ case GDK_KEY_PRESS: if (event->key.keyval == GDK_KEY_Escape) popup_window_hide(window); break; /* Broken grab, hide popup */ case GDK_GRAB_BROKEN: popup_window_hide(window); break; /* Unhandle event, do nothing */ default: break; } return FALSE; }
static void gtk_real_button_activate (GtkButton *button) { GtkWidget *widget = GTK_WIDGET (button); GtkButtonPrivate *priv = button->priv; GdkDevice *device; device = gtk_get_current_event_device (); if (device && gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD) device = gdk_device_get_associated_device (device); if (gtk_widget_get_realized (widget) && !priv->activate_timeout) { /* bgo#626336 - Only grab if we have a device (from an event), not if we * were activated programmatically when no event is available. */ if (device && gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) { if (gdk_seat_grab (gdk_device_get_seat (device), priv->event_window, GDK_SEAT_CAPABILITY_KEYBOARD, TRUE, NULL, NULL, NULL, NULL) == GDK_GRAB_SUCCESS) { gtk_device_grab_add (widget, device, TRUE); priv->grab_keyboard = device; } } priv->activate_timeout = gdk_threads_add_timeout (ACTIVATE_TIMEOUT, button_activate_timeout, button); g_source_set_name_by_id (priv->activate_timeout, "[gtk+] button_activate_timeout"); priv->button_down = TRUE; gtk_button_update_state (button); } }
static void grab_window_toggled (GtkToggleButton *button, GtkWidget *widget) { GdkDevice *device = gtk_get_current_event_device (); GdkSeat *seat = gdk_device_get_seat (device); if (gtk_toggle_button_get_active (button)) { int status; status = gdk_seat_grab (seat, gtk_widget_get_window (widget), GDK_SEAT_CAPABILITY_KEYBOARD, FALSE, NULL, NULL, NULL, NULL); if (status != GDK_GRAB_SUCCESS) g_warning ("Could not grab keyboard! (%s)", grab_string (status)); } else { gdk_seat_ungrab (seat); } }
static void gnc_date_edit_popup (GNCDateEdit *gde) { GtkWidget *toplevel; struct tm mtm; gboolean date_was_valid; GdkDevice *device, *keyboard, *pointer; g_return_if_fail (GNC_IS_DATE_EDIT (gde)); ENTER("gde %p", gde); device = gtk_get_current_event_device (); /* This code is pretty much just copied from gtk_date_edit_get_date */ date_was_valid = qof_scan_date (gtk_entry_get_text (GTK_ENTRY (gde->date_entry)), &mtm.tm_mday, &mtm.tm_mon, &mtm.tm_year); if (!date_was_valid) { /* No valid date. Hacky workaround: Instead of crashing we randomly choose today's date. */ gnc_tm_get_today_start(&mtm); } mtm.tm_mon--; /* Hope the user does not actually mean years early in the A.D. days... * This date widget will obviously not work for a history program :-) */ if (mtm.tm_year >= 1900) mtm.tm_year -= 1900; gnc_tm_set_day_start(&mtm); /* Set the calendar. */ gtk_calendar_select_day (GTK_CALENDAR (gde->calendar), 1); gtk_calendar_select_month (GTK_CALENDAR (gde->calendar), mtm.tm_mon, 1900 + mtm.tm_year); gtk_calendar_select_day (GTK_CALENDAR (gde->calendar), mtm.tm_mday); /* Make sure we'll get notified of clicks outside the popup * window so we can properly pop down if that happens. */ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (gde)); if (GTK_IS_WINDOW (toplevel)) { gtk_window_group_add_window ( gtk_window_get_group (GTK_WINDOW (toplevel)), GTK_WINDOW (gde->cal_popup)); gtk_window_set_transient_for (GTK_WINDOW (gde->cal_popup), GTK_WINDOW (toplevel)); } position_popup (gde); gtk_widget_show (gde->cal_popup); gtk_widget_grab_focus (gde->cal_popup); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gde->date_button), TRUE); if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) { keyboard = device; pointer = gdk_device_get_associated_device (device); } else { pointer = device; keyboard = gdk_device_get_associated_device (device); } if (!gtk_widget_has_focus (gde->calendar)) gtk_widget_grab_focus (gde->calendar); if (!popup_grab_on_window (gtk_widget_get_window ((GTK_WIDGET(gde->cal_popup))), keyboard, pointer, GDK_CURRENT_TIME)) { gtk_widget_hide (gde->cal_popup); LEAVE("Failed to grab window"); return; } gtk_grab_add (gde->cal_popup); LEAVE(" "); }
static gboolean on_auto_scroll(gpointer user_data) { FmDndAutoScroll* as = (FmDndAutoScroll*)user_data; int x, y; GtkAdjustment* va = as->vadj; GtkAdjustment* ha = as->hadj; GtkWidget* widget = as->widget; GtkAllocation allocation; gdk_window_get_device_position (gtk_widget_get_window(widget), gtk_get_current_event_device(), &x, &y, NULL); gtk_widget_get_allocation(widget, &allocation); /* HACK. Sometimes we do not get drag-leave signal. (Why?) This check prevents infinite scrolling. */ if (y < 0 || y > allocation.height || x < 0 || x > allocation.width) { as->timeout = 0; return FALSE; } if(va) { if(y < SCROLL_EDGE_SIZE) /* scroll up */ { gdouble value = gtk_adjustment_get_value(va); gdouble lower = gtk_adjustment_get_lower(va); if(value > lower) { value -= gtk_adjustment_get_step_increment(va); if(value < lower) value = lower; gtk_adjustment_set_value(va, value); } } else if(y > (allocation.height - SCROLL_EDGE_SIZE)) { gdouble value = gtk_adjustment_get_value(va); gdouble upper = gtk_adjustment_get_upper(va) - gtk_adjustment_get_page_size(va); /* scroll down */ if(value < upper) { value += gtk_adjustment_get_step_increment(va); if(value > upper) value = upper; gtk_adjustment_set_value(va, value); } } gtk_adjustment_value_changed(va); } if(ha) { if(x < SCROLL_EDGE_SIZE) /* scroll to left */ { gdouble value = gtk_adjustment_get_value(ha); gdouble lower = gtk_adjustment_get_lower(ha); if(value > lower) { value -= gtk_adjustment_get_step_increment(ha); if(value < lower) value = lower; gtk_adjustment_set_value(ha, value); } } else if(x > (allocation.width - SCROLL_EDGE_SIZE)) { gdouble value = gtk_adjustment_get_value(ha); gdouble upper = gtk_adjustment_get_upper(ha) - gtk_adjustment_get_page_size(ha); /* scroll to right */ if(value < upper) { value += gtk_adjustment_get_step_increment(ha); if(value > upper) value = upper; gtk_adjustment_set_value(ha, value); } } gtk_adjustment_value_changed(ha); } return TRUE; }
/** * gnm_cell_combo_view_popdown: * @sov: #SheetObjectView * @activate_time: event time * * Open the popup window associated with @sov **/ void gnm_cell_combo_view_popdown (SheetObjectView *sov, guint32 activate_time) { GocItem *view = GOC_ITEM (sov); GnmPane *pane = GNM_PANE (view->canvas); SheetControlGUI *scg = pane->simple.scg; SheetObject *so = sheet_object_view_get_so (sov); Sheet const *sheet = sheet_object_get_sheet (so); GtkWidget *frame, *popup, *list, *container; int root_x, root_y; gboolean make_buttons = FALSE; GtkTreePath *clip = NULL, *select = NULL; GtkWindow *toplevel = wbcg_toplevel (scg_wbcg (scg)); GdkWindow *popup_window; GdkDevice *device; GnmRange const *merge; popup = gtk_window_new (GTK_WINDOW_POPUP); gtk_window_set_type_hint (GTK_WINDOW (popup), GDK_WINDOW_TYPE_HINT_COMBO); gtk_window_group_add_window (gtk_window_get_group (toplevel), GTK_WINDOW (popup)); go_gtk_window_set_transient (toplevel, GTK_WINDOW (popup)); gtk_window_set_resizable (GTK_WINDOW (popup), FALSE); gtk_window_set_decorated (GTK_WINDOW (popup), FALSE); gtk_window_set_screen (GTK_WINDOW (popup), gtk_widget_get_screen (GTK_WIDGET (toplevel))); list = ccombo_create_list (GNM_CCOMBO_VIEW (sov), so, &clip, &select, &make_buttons); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE); g_object_set_data (G_OBJECT (list), SOV_ID, sov); frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); #if 0 range_dump (&so->anchor.cell_bound, ""); g_printerr (" : so = %p, view = %p\n", so, view); #endif if (clip != NULL) { GtkWidget *sw = gtk_scrolled_window_new ( gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (list)), gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (list))); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); g_object_set_data_full (G_OBJECT (list), "clip", clip, (GDestroyNotify)gtk_tree_path_free); gtk_container_add (GTK_CONTAINER (sw), list); /* * Do the sizing in a realize handler as newer versions of * gtk+ give us zero sizes until then. */ g_signal_connect_after (list, "realize", G_CALLBACK (cb_realize_treeview), sw); container = sw; } else container = list; if (make_buttons) { GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); GtkWidget *hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); GtkWidget *button; button = gtk_button_new_from_stock (GTK_STOCK_CANCEL); g_signal_connect_swapped (button, "clicked", G_CALLBACK (cb_ccombo_cancel_button), list); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 6); button = gtk_button_new_from_stock (GTK_STOCK_OK); g_signal_connect_swapped (button, "clicked", G_CALLBACK (cb_ccombo_ok_button), list); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 6); gtk_box_pack_start (GTK_BOX (vbox), container, FALSE, TRUE, 6); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 6); container = vbox; } gtk_container_add (GTK_CONTAINER (frame), container); /* do the popup */ gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (pane)), &root_x, &root_y); if (sheet->text_is_rtl) { GtkAllocation pa; gtk_widget_get_allocation (GTK_WIDGET (pane), &pa); root_x += pa.width; root_x -= scg_colrow_distance_get (scg, TRUE, pane->first.col, so->anchor.cell_bound.start.col + 1); } else root_x += scg_colrow_distance_get (scg, TRUE, pane->first.col, so->anchor.cell_bound.start.col); merge = gnm_sheet_merge_is_corner (sheet, &(so->anchor.cell_bound.start)); gtk_window_move (GTK_WINDOW (popup), root_x, root_y + scg_colrow_distance_get (scg, FALSE, pane->first.row, so->anchor.cell_bound.start.row + ((merge == NULL) ? 1 : range_height (merge)))); gtk_container_add (GTK_CONTAINER (popup), frame); g_signal_connect (popup, "key_press_event", G_CALLBACK (cb_ccombo_key_press), list); g_signal_connect (popup, "button_press_event", G_CALLBACK (cb_ccombo_button_press), list); g_signal_connect_after (popup, "button_release_event", G_CALLBACK (cb_ccombo_button_release), list); g_signal_connect (list, "motion_notify_event", G_CALLBACK (cb_ccombo_list_motion), list); g_signal_connect (list, "button_press_event", G_CALLBACK (cb_ccombo_list_button_press), popup); gtk_widget_show_all (popup); /* after we show the window setup the selection (showing the list * clears the selection) */ if (select != NULL) { gtk_tree_selection_select_path ( gtk_tree_view_get_selection (GTK_TREE_VIEW (list)), select); gtk_tree_view_set_cursor (GTK_TREE_VIEW (list), select, NULL, FALSE); gtk_tree_path_free (select); } gtk_widget_grab_focus (popup); gtk_widget_grab_focus (GTK_WIDGET (list)); ccombo_focus_change (GTK_WIDGET (list), TRUE); popup_window = gtk_widget_get_window (popup); device = gtk_get_current_event_device (); if (0 == gdk_device_grab (device, popup_window, GDK_OWNERSHIP_APPLICATION, TRUE, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK, NULL, activate_time)) { if (0 == gdk_device_grab (gdk_device_get_associated_device (device), popup_window, GDK_OWNERSHIP_APPLICATION, TRUE, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, NULL, activate_time)) gtk_grab_add (popup); else gdk_device_ungrab (device, activate_time); } }
static void emoticon_tool_button_popup (EEmoticonToolButton *button) { GtkToggleToolButton *tool_button; GdkWindow *window; gboolean grab_status; GdkDevice *device, *mouse, *keyboard; guint32 activate_time; device = gtk_get_current_event_device (); g_return_if_fail (device != NULL); if (!gtk_widget_get_realized (GTK_WIDGET (button))) return; if (button->priv->popup_shown) return; activate_time = gtk_get_current_event_time (); if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) { keyboard = device; mouse = gdk_device_get_associated_device (device); } else { keyboard = gdk_device_get_associated_device (device); mouse = device; } /* Position the window over the button. */ emoticon_tool_button_reposition_window (button); /* Show the pop-up. */ gtk_widget_show (button->priv->window); gtk_widget_grab_focus (button->priv->window); /* Activate the tool button. */ tool_button = GTK_TOGGLE_TOOL_BUTTON (button); gtk_toggle_tool_button_set_active (tool_button, TRUE); /* Try to grab the pointer and keyboard. */ window = gtk_widget_get_window (button->priv->window); grab_status = !keyboard || gdk_device_grab ( keyboard, window, GDK_OWNERSHIP_WINDOW, TRUE, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, NULL, activate_time) == GDK_GRAB_SUCCESS; if (grab_status) { grab_status = !mouse || gdk_device_grab (mouse, window, GDK_OWNERSHIP_WINDOW, TRUE, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK, NULL, activate_time) == GDK_GRAB_SUCCESS; if (!grab_status && keyboard) gdk_device_ungrab (keyboard, activate_time); } if (grab_status) { gtk_device_grab_add (button->priv->window, mouse, TRUE); button->priv->grab_keyboard = keyboard; button->priv->grab_mouse = mouse; } else { gtk_widget_hide (button->priv->window); } }