gtk3 – 自gtk版本3.22起不推荐使用’gdk_screen_get_active_win
根据
https://developer.gnome.org/gdk3/stable/GdkScreen.html#gdk-screen-get-active-window,
但是,应该使用什么呢? (这是许多已弃用的GdkScreen功能之一.) 具体而言,我如何获得活动窗口的位置和几何? 编辑12/10/16:经过几天的调查,我得出结论,这个问题的答案在developer.gnome.org之外.可能需要直接针对X11,wayland和mir编写单独的代码. 对于它的价值,下面是我编写的get_window-areas.c,它探讨了在不使用弃用函数的情况下可以在Gtk中找到的内容.似乎没有办法获得窗口标题或活动状态;所以,我无法复制@ theGtknerd使用不稳定Wnck库的答案的功能. 我只是在学习Gtk,所以我非常感谢你提出的改进意见.我从空窗口代码https://developer.gnome.org/gtk3/stable/gtk-getting-started.html#id-1.2.3.5开始,向其添加带缓冲区的textview,然后将有关每个窗口的几何和位置的信息插入到文本缓冲区中. gcc `pkg-config --cflags gtk+-3.0` -o get_window-areas get_window-areas.c `pkg-config --libs gtk+-3.0` 使用上面的gcc命令编译下面的get_window-areas.c. #include <gtk/gtk.h> static void activate (GtkApplication* app,gpointer user_data) { GtkWidget *window = NULL; GtkWidget *text_view; GtkTextBuffer *buffer; int x = 0,y = 0,width = 0,height = 0; char char_x[5],char_y[5],char_width[5],char_height[5]; GdkScreen *screen; GdkWindow *dwindow; GList *gl_item = NULL,*gl = NULL; window = gtk_application_window_new (app); screen = gtk_window_get_screen (GTK_WINDOW(window)); buffer = gtk_text_buffer_new (NULL); text_view = gtk_text_view_new_with_buffer (buffer); gtk_container_add (GTK_CONTAINER (window),text_view); if(screen != NULL) { gl = gdk_screen_get_window_stack(screen); for (gl_item = g_list_first(gl); gl_item != NULL; gl_item = gl_item->next) { dwindow=gl_item->data; gdk_window_get_root_origin(dwindow,&x,&y); width = gdk_window_get_width(dwindow); height = gdk_window_get_height(dwindow); g_object_unref(dwindow); snprintf (char_x,5,"%d",x); snprintf (char_y,y); snprintf (char_width,width); snprintf (char_height,height); gtk_text_buffer_insert_at_cursor(buffer,char_width,-1); gtk_text_buffer_insert_at_cursor(buffer,"x",char_height," at (",char_x,",char_y,")n",-1); }; g_list_free (gl); } else {gtk_text_buffer_insert_at_cursor(buffer,"Failed to get default screen.n",-1);} gtk_widget_show_all (window); } int main (int argc,char **argv) { GtkApplication *app; int status; app = gtk_application_new ("com.github.colinkeenan.silentcast",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; } 解决方法
(编辑3/11/17以通过在打开时关闭显示来消除内存泄漏)
(编辑3/6/17以在get_top_window中初始化s) (编辑12/24以提供X11的完整答案,并标记为正确答案,直到某人有一般解决方案).这是我在github上重写/重构我的silentcast应用程序(之前只是使用yad for UI的一系列bash脚本)的一部分,尽管我还没有在github上放置任何这个Gtk代码. 我下面的“正确答案”允许你实际获得有效的GdkWindow,它的几何和几何.范围,或带有子项的活动X11窗口,以及它的几何. 正确答案 (请注意,它仅适用于X11,因此应包含并编译gtk / gtkx.h,而不是gtk / gtk.h) .h文件 /* * Filename: SC_X11_get_active_window.h * App Name: Silentcast <https://github.com/colinkeenan/silentcast> * Copyright ? 2016,2017 Colin N Keenan <colinnkeenan@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License,or * (at your option) any later version. * * This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not,see <http://www.gnu.org/licenses/>. * * Description: defines some custom X11 error messags and exposes 3 functions: * SC_get_active_gdkwindow (...),SC_get_geomeotry_for (...),* and SC_get_active_windows_and_geometry (...) */ #include <gtk/gtkx.h> #define SC_X11_ERROR0 " n" #define SC_X11_ERROR1 "Failed to connect to X server.n" #define SC_X11_ERROR2 "x11 error trying to get focused windown" #define SC_X11_ERROR3 "X11 reports no focused windown" #define SC_X11_ERROR4 "X11 error trying to get top windown" #define D_ERR 1 #define FOCUS_ERR1 2 #define FOCUS_ERR2 3 #define TOP_ERR 4 #define UKN_ERR 5 #define SC_X11_E1 D_ERR #define SC_X11_E2 FOCUS_ERR1 #define SC_X11_E3 FOCUS_ERR2 #define SC_X11_E4 TOP_ERR #define SC_X11_E0 UKN_ERR unsigned int SC_get_active_X11window (Window *w,Window* *w_children,ssize_t *n); gboolean SC_get_active_gdkwindow (Window aw,Window *aw_children,ssize_t n,GdkWindow* *gdkwindow); void SC_get_geometry_for (Window aw,int *x,int *y,unsigned int *width,unsigned int *height,GdkRectangle *extents,GdkWindow* *gdkwindow); gboolean SC_get_active_windows_and_geometry (Window *aw,Window* *aw_children,ssize_t *n,GdkWindow* *gdkwindow); .c文件 /* * Filename: SC_X11_get_active_window.c * App Name: Silentcast <https://github.com/colinkeenan/silentcast> * Copyright ? 2016 Colin N Keenan <colinnkeenan@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License,see <http://www.gnu.org/licenses/>. * * Description: adapted from "get the active window on X window system" * https://gist.github.com/kui/2622504 * to get Gdk geometry of the active window,both the * inner window and the extents */ #include "SC_X11_get_active_window.h" Bool xerror = False; static int handle_error (Display* display,XErrorEvent* error) { xerror = True; return 1; } static int get_focus_window (Display* d,Window *w) { int revert_to; XGetInputFocus (d,w,&revert_to); if (xerror) return FOCUS_ERR1; //X error trying to get focused window else if (w == None) return FOCUS_ERR2; //no focused window else return 0; } static int get_top_window (Display* d,Window start,Window *w,ssize_t *n) { Window parent = start,root = None,*children = NULL; *w = start; unsigned int nchildren; Status s = XQueryTree (d,*w,&root,&parent,&children,&nchildren),s_prev; /* ultimately trying to get *w and *w_children */ while (parent != root && !xerror) { *w = parent; //previous parent s_prev = s; //previous status of XQueryTree if (s_prev) { *w_children = children; //previous children *n = nchildren; //previous number of children } s = XQueryTree (d,&nchildren); /* When parent == root,the previous "parent" is the top window. * Save the children of the top window too,but XFree all other * children. */ if (parent != root) { // parent is not root,so previous parent wasn't top window,so don't need it's children if (s_prev) XFree (*w_children); } else if (s) XFree (children); // don't keep the children of root either } if (xerror) return TOP_ERR; else return 0; } unsigned int SC_get_active_X11window (Window *w,ssize_t *n) { Display* d = NULL; unsigned int e = 0; XSetErrorHandler (handle_error); d = XOpenDisplay (NULL); if (d == NULL) { return D_ERR; } else { /* set w to the focused window */ e = get_focus_window (d,w); if (e) { //if error XCloseDisplay (d); return e; } /* get_top_window will set w to the top focused window (active window) */ e = get_top_window (d,w_children,n); if (e) { //if error XCloseDisplay (d); return e; } XCloseDisplay(d); } return 0; //no error } /* SC_get_active_gdkwindow (...) tries to match a GdkWindow to one of the passed X11 * windows (supposed to be the active X11 window and it's n children),and returns * TRUE if such a match is found,FALSE if not */ gboolean SC_get_active_gdkwindow (Window aw,GdkWindow* *gdkwindow) { ssize_t i = 0; GdkWindow *dwindow = NULL; GdkScreen *screen = NULL; GList *gl_item = NULL,*gl = NULL; gboolean active_window_found = FALSE; screen = gdk_screen_get_default (); if (screen != NULL) { /* Go through all windows known to Gtk and check XID against active X11 window,aw. */ gl = gdk_screen_get_window_stack (screen); for (gl_item = g_list_first (gl); !active_window_found && gl_item != NULL; gl_item = gl_item->next) { dwindow = gl_item->data; if (gdk_x11_window_get_xid (dwindow) == aw) active_window_found = TRUE; else for (i = 0; i < n; i++) //aw didn't match this dwindow,so check all of aw_children if (gdk_x11_window_get_xid (dwindow) == aw_children[i]) active_window_found = TRUE; if (!active_window_found) g_object_unref (dwindow); else *gdkwindow = dwindow; } g_list_free (gl); } return active_window_found; } /* SC_get_geometry_for (...) trys to get the Gdk geometry for the GdkWindow * matching the passed X11 window with children,getting both the internal * window geometry and it's extents (title-bar/frame). If can't get Gdk info * will get the X11 geometry,setting both inner and extents geometry to * the same values. */ void SC_get_geometry_for (Window aw,GdkRectangle *win_rect,GdkWindow* *dwindow) { unsigned int bwidth = 0,depth = 0,width,height; int x,y; Window root = 0; if (SC_get_active_gdkwindow (aw,aw_children,n,dwindow)) { gdk_window_get_frame_extents (*dwindow,extents); //{top-left corner,width & height} of title-bar/borders gdk_window_get_origin(*dwindow,&y); //top-left corner of interior window (not title bar/borders) width = gdk_window_get_width (*dwindow); //width of interior window height = gdk_window_get_height (*dwindow); //height of interior window win_rect->x = x; win_rect->y = y; win_rect->width = (int) width; win_rect->height = (int) height; } else { fprintf (stderr,"Failed to get GdkWindow. Falling back on X11 geometry of active window,saved as both extents and interior geometry."); Display* d = XOpenDisplay (NULL); if (d) { XGetGeometry (d,aw,&y,&width,&height,&bwidth,&depth); XCloseDisplay (d); extents->x = x; extents->y = y; extents->width = (int) width; extents->height = (int) height; } } } /* SC_get_active_windows_and_geometry (...) calls get_active_x11window (...) to get the active X11 window * and it's children,then calls SC_get_geometry_for (...) to get geometry (hopefully Gdk) that matches */ gboolean SC_get_active_windows_and_geometry (Window *aw,GdkWindow* *dwindow) { switch (SC_get_active_X11window(aw,n)) { get aw,and n (number of children) case 0: SC_get_geometry_for (*aw,*aw_children,*n,win_rect,extents,dwindow); return TRUE; case SC_X11_E1: fprintf (stderr,SC_X11_ERROR1); break; case SC_X11_E2: fprintf (stderr,SC_X11_ERROR2); break; case SC_X11_E3: fprintf (stderr,SC_X11_ERROR3); break; case SC_X11_E4: fprintf (stderr,SC_X11_ERROR4); break; } return FALSE; //failed to get active window due to X11 error } 我以前的答案通常得到正确的几何,但不是窗口 我修改了“在X窗口系统上获取活动窗口”https://gist.github.com/kui/2622504的代码,以便在问题中使用我的示例.我把它变成了一个图书馆.我没有将此标记为正确的答案,因为这是我写过的第一个库文件,我也是Gtk的新手.我也没有太多编写C代码的经验.最后,正确答案应包括X11,Wayland和MIR的库.我很高兴看到一个答案,包括我的图书馆,改进了缺少的两个库. 编译如下: gcc `pkg-config --cflags gtk+-3.0` -o get_window-areas X11_get_active_window_geometry.c get_window-areas.c `pkg-config --libs gtk+-3.0` -lX11 X11_get_active_window_geometry.h #include <X11/Xlib.h> #define SC_X11_ERROR0 "Uknown error from get_actve_window_geometry.n" #define SC_X11_ERROR1 "Failed to connect to X server.n" #define SC_X11_ERROR2 "x11 error trying to get focused windown" #define SC_X11_ERROR3 "X11 reports no focused windown" #define SC_X11_ERROR4 "X11 error trying to get top windown" #define SC_X11_ERROR5 "X11 error trying to get the active-window geometry.n" #define D_ERR 1 #define FOCUS_ERR1 2 #define FOCUS_ERR2 3 #define TOP_ERR 4 #define GEOM_ERR 5 #define SC_X11_E1 D_ERR #define SC_X11_E2 FOCUS_ERR1 #define SC_X11_E3 FOCUS_ERR2 #define SC_X11_E4 TOP_ERR #define SC_X11_E5 GEOM_ERR unsigned int get_active_window_geometry (int *x,unsigned int *height); X11_get_active_window_geometry.c #include "X11_get_active_window_geometry.h" Bool xerror = False; static int handle_error (Display* display,&revert_to); if (xerror) return FOCUS_ERR1; //X error trying to get focused window else if (w == None) return FOCUS_ERR2; //no focused window else return 0; } static int get_top_window (Display* d,Window *w){ Window parent = start,*children; *w = start; unsigned int nchildren; Status s; while (parent != root && !xerror) { *w = parent; s = XQueryTree (d,&nchildren); if (s) XFree (children); } if (xerror) return TOP_ERR; else return 0; } unsigned int get_active_window_geometry (int *x,unsigned int *height) { Display* d = NULL; Window root,w; unsigned int bwidth = 0,e = 0; XSetErrorHandler (handle_error); d = XOpenDisplay (NULL); if (d == NULL) { return D_ERR; } else { e = get_focus_window (d,&w); //get focused window w if (e) return e; e = get_top_window (d,&w); //get top focused window w (the active window) if (e) return e; XGetGeometry (d,x,y,height,&depth); if (xerror) return GEOM_ERR; } return 0; } get_active_window.c #include <gtk/gtk.h> #include "X11_get_active_window_geometry.h" static void activate (GtkApplication* app,gpointer user_data) { GtkWidget *window = NULL,*text_view; GtkTextBuffer *buffer; unsigned int width = 0,height = 0,widtha = 0,heighta = 0,iwidtha = 0,iheighta = 0; int x = 0,xa = 0,ya = 0,ixa =0,iya = 0; GdkRectangle extents= { 0,0 }; char char_x[5],char_height[5]; GdkScreen *screen; GdkWindow *dwindow; GList *gl_item = NULL,*gl = NULL; window = gtk_application_window_new (app); screen = gtk_window_get_screen (GTK_WINDOW(window)); buffer = gtk_text_buffer_new (NULL); text_view = gtk_text_view_new_with_buffer (buffer); gtk_container_add (GTK_CONTAINER (window),text_view); #define ADD_TEXT(STRING) gtk_text_buffer_insert_at_cursor (buffer,STRING,-1) #define ADD_INT(CHAR_INT,INT) snprintf (CHAR_INT,INT); ADD_TEXT(CHAR_INT); #define ADD_GEOMETRY_TEXT(X,Y,WIDTH,HEIGHT) ADD_INT(char_width,WIDTH); ADD_TEXT("x"); ADD_INT(char_height,HEIGHT); ADD_TEXT(" at ("); ADD_INT(char_x,X); ADD_TEXT(","); ADD_INT(char_y,Y); ADD_TEXT(")n"); /* get active window geometry using X11 and handle error,if any*/ switch (get_active_window_geometry(&xa,&ya,&widtha,&heighta)) { case 0: ADD_TEXT("GEOMETRY FOR ACTIVE WINDOW USING X11n"); ADD_GEOMETRY_TEXT(xa,ya,widtha,heighta); ADD_TEXT("n"); break; case SC_X11_E1: ADD_TEXT(SC_X11_ERROR1); break; case SC_X11_E2: ADD_TEXT(SC_X11_ERROR2); break; case SC_X11_E3: ADD_TEXT(SC_X11_ERROR3); break; case SC_X11_E4: ADD_TEXT(SC_X11_ERROR4); break; case SC_X11_E5: ADD_TEXT(SC_X11_ERROR5); break; default: ADD_TEXT(SC_X11_ERROR0); } /* get window geometry for all windows using Gtk and identify the active one by comparison with X11 result*/ if (screen != NULL) { ADD_TEXT("GEOMETRY FOR ALL WINDOWS USING Gtk:nn"); gl = gdk_screen_get_window_stack (screen); for (gl_item = g_list_first (gl); gl_item != NULL; gl_item = gl_item->next) { dwindow=gl_item->data; gdk_window_get_frame_extents (dwindow,&extents); //{top-left corner,width & height} of title-bar/borders ADD_TEXT("Entirety of Window: "); ADD_GEOMETRY_TEXT(extents.x,extents.y,extents.width,extents.height); gdk_window_get_origin(dwindow,&y); //top-left corner of interior window (not title bar/borders) width = gdk_window_get_width (dwindow); //width of interior window height = gdk_window_get_height (dwindow); //height of interior window ADD_TEXT("Interior of Window: "); ADD_GEOMETRY_TEXT(x,height); ADD_TEXT("n"); /*If extents matches active window geometry,save interior window geometry */ if (extents.x == xa && extents.y == ya && extents.width == widtha && extents.height == heighta) { ixa = x; iya = y; iwidtha = width; iheighta = height; } g_object_unref (dwindow); }; g_list_free (gl); ADD_TEXT("MATCHING THE ACTIVE WINDOW REPORTED BY X11 WITH THE GTK WINDOW GEOMETRIES:n"); ADD_TEXT("Entirety of Active Window: "); ADD_GEOMETRY_TEXT(xa,heighta); ADD_TEXT("Interior of Active Window: "); ADD_GEOMETRY_TEXT(ixa,iya,iwidtha,iheighta); } else { ADD_TEXT("Failed to get default screen.n"); } gtk_widget_show_all (window); } int main (int argc,argv); g_object_unref (app); return status; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 使用Windows身份验证与php?
- windows-server-2008 – 在EC2上部署网站数据库有什么好处:
- windows-server-2008 – 是否可以在没有活动目录的情况下设
- 调试 – 如何在Windows Phone 7上调试“未指定的错误”?
- windowsserver 2012 R2 创建群集失败
- 窗口 – 保持自动控制的远程桌面会话“活着”
- Leetcode 480. Sliding Window Median
- windows – Delphi – 如何防止窗体/ MsgBoxes在以前的窗体
- windows – 让批处理文件最小化DOS窗口?
- windows – Delphi中的跨应用程序拖放
- iis-7 – 从IIS中的WindowsAuthentication中删除
- YAPI windows 二次开发 树形结构 多层级结构 拖拽
- window不卸载切换node
- .net – 自定义UI – Windows还是Linux?
- 无法在Windows上安装cairo haskell绑定
- 缓存 – 缓存DataContractSerializer实例是一个好
- windows-server-2012 – Server Manager 2012 –
- Win10,Python 3.6环境下安装PyQt4
- 无法调试Windows Azure云服务项目.输出目录不存在
- 将我的DLL部署到GAC,引用其他DLL不在GAC中