如何通过子部件的GtkGestureClick实现GtkWindow拖拽移动(替换废弃API)
替换废弃的
gtk_widget_translate_coordinates为gtk_widget_compute_point实现窗口拖拽 我通过点击并按住GtkWindow的子部件来拖拽移动窗口,现有代码可正常运行,但编译时出现警告:'gtk_widget_translate_coordinates已废弃,请使用gtk_widget_compute_point替代'。以下是修改后的代码,替换了废弃的API:
原代码
#include <gtk/gtk.h> static void start_move (GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) { GtkWidget *widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)); GdkSurface *surface; GdkEvent *event; guint button; guint32 timestamp; gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED); surface = gtk_native_get_surface (gtk_widget_get_native (widget)); event = gtk_event_controller_get_current_event (GTK_EVENT_CONTROLLER (gesture)); if (gdk_event_get_event_type (event) == GDK_BUTTON_PRESS) button = gdk_button_event_get_button (event); else button = 0; timestamp = gdk_event_get_time (event); gtk_widget_translate_coordinates (widget, GTK_WIDGET (gtk_widget_get_root (widget)), x, y, &x, &y); gdk_toplevel_begin_move (GDK_TOPLEVEL (surface), gdk_event_get_device (event), button, x, y, timestamp); gtk_event_controller_reset (GTK_EVENT_CONTROLLER (gesture)); } static void activate (GtkApplication *app, gpointer user_data) { GtkWidget *window = gtk_application_window_new (app); gtk_window_set_title (GTK_WINDOW (window), "example"); GtkWidget *fixed = gtk_fixed_new (); gtk_window_set_child ((GtkWindow *)window, fixed); gtk_widget_set_size_request (fixed, 400, 200); GtkWidget *c_btn = gtk_button_new_from_icon_name ("window-close-symbolic"); gtk_fixed_put (GTK_FIXED (fixed), c_btn, 125, 90); GtkGesture *gesture; gesture = gtk_gesture_click_new (); g_signal_connect (gesture, "pressed", G_CALLBACK (start_move), NULL); gtk_widget_add_controller (c_btn, GTK_EVENT_CONTROLLER (gesture)); gtk_window_present ((GtkWindow*)window); } int main (int argc, char **argv) { GtkApplication *app; int status; app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE); g_signal_connect (app, "activate", G_CALLBACK (activate), NULL); status = g_application_run (G_APPLICATION (app), argc, argv); g_object_unref (app); return status; }
修改后的代码(替换废弃API)
#include <gtk/gtk.h> static void start_move (GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) { GtkWidget *widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)); GdkSurface *surface; GdkEvent *event; guint button; guint32 timestamp; gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED); surface = gtk_native_get_surface (gtk_widget_get_native (widget)); event = gtk_event_controller_get_current_event (GTK_EVENT_CONTROLLER (gesture)); if (gdk_event_get_event_type (event) == GDK_BUTTON_PRESS) button = gdk_button_event_get_button (event); else button = 0; timestamp = gdk_event_get_time (event); // 替换废弃的gtk_widget_translate_coordinates为gtk_widget_compute_point GdkPoint point = { .x = (int)x, .y = (int)y }; gtk_widget_compute_point(widget, GTK_WIDGET(gtk_widget_get_root(widget)), &point, &point); x = point.x; y = point.y; gdk_toplevel_begin_move (GDK_TOPLEVEL (surface), gdk_event_get_device (event), button, x, y, timestamp); gtk_event_controller_reset (GTK_EVENT_CONTROLLER (gesture)); } static void activate (GtkApplication *app, gpointer user_data) { GtkWidget *window = gtk_application_window_new (app); gtk_window_set_title (GTK_WINDOW (window), "example"); GtkWidget *fixed = gtk_fixed_new (); gtk_window_set_child ((GtkWindow *)window, fixed); gtk_widget_set_size_request (fixed, 400, 200); GtkWidget *c_btn = gtk_button_new_from_icon_name ("window-close-symbolic"); gtk_fixed_put (GTK_FIXED (fixed), c_btn, 125, 90); GtkGesture *gesture; gesture = gtk_gesture_click_new (); g_signal_connect (gesture, "pressed", G_CALLBACK (start_move), NULL); gtk_widget_add_controller (c_btn, GTK_EVENT_CONTROLLER (gesture)); gtk_window_present ((GtkWindow*)window); } int main (int argc, char **argv) { GtkApplication *app; int status; app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE); g_signal_connect (app, "activate", G_CALLBACK (activate), NULL); status = g_application_run (G_APPLICATION (app), argc, argv); g_object_unref (app); return status; }
关键修改说明
gtk_widget_compute_point的作用是将源部件坐标系下的点转换为目标部件坐标系下的点,核心用法:
- 第一个参数:源部件(触发拖拽的子部件
widget) - 第二个参数:目标部件(根窗口
gtk_widget_get_root(widget),与原API的目标一致) - 第三个参数:输入点(需要先将
double类型的点击位置转为int,构造GdkPoint) - 第四个参数:输出点(直接复用同一个
GdkPoint变量存储转换后的结果)
转换完成后,将GdkPoint的x、y赋值回原变量,后续的窗口拖拽逻辑保持不变。
内容的提问来源于stack exchange,提问作者dibyendu
相关产品推荐
相关产品推荐

