x11: Add EWMH workspace handling api
Add a few functions that give access to the EWMH workspace properties.
This commit is contained in:
@@ -998,6 +998,8 @@ gdk_x11_screen_get_window_manager_name
|
||||
gdk_x11_screen_get_monitor_output
|
||||
gdk_x11_screen_lookup_visual
|
||||
gdk_x11_screen_supports_net_wm_hint
|
||||
gdk_x11_screen_get_number_of_desktops
|
||||
gdk_x11_screen_get_current_desktop
|
||||
gdk_x11_window_foreign_new_for_display
|
||||
gdk_x11_window_lookup_for_display
|
||||
gdk_x11_window_get_xid
|
||||
@@ -1005,6 +1007,8 @@ gdk_x11_window_set_hide_titlebar_when_maximized
|
||||
gdk_x11_window_set_theme_variant
|
||||
gdk_x11_window_set_user_time
|
||||
gdk_x11_window_move_to_current_desktop
|
||||
gdk_x11_window_move_to_desktop
|
||||
gdk_x11_window_get_desktop
|
||||
gdk_x11_window_set_utf8_property
|
||||
gdk_x11_get_default_root_xwindow
|
||||
gdk_x11_get_default_screen
|
||||
|
||||
@@ -1722,3 +1722,74 @@ gdk_x11_screen_class_init (GdkX11ScreenClass *klass)
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
}
|
||||
|
||||
static guint32
|
||||
get_netwm_cardinal_property (GdkScreen *screen,
|
||||
const gchar *name)
|
||||
{
|
||||
GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
|
||||
GdkAtom atom;
|
||||
guint32 prop = 0;
|
||||
Atom type;
|
||||
gint format;
|
||||
gulong nitems;
|
||||
gulong bytes_after;
|
||||
guchar *data;
|
||||
|
||||
atom = gdk_atom_intern_static_string (name);
|
||||
|
||||
if (!gdk_x11_screen_supports_net_wm_hint (screen, atom))
|
||||
return 0;
|
||||
|
||||
XGetWindowProperty (x11_screen->xdisplay,
|
||||
x11_screen->xroot_window,
|
||||
gdk_x11_get_xatom_by_name_for_display (GDK_SCREEN_DISPLAY (screen), name),
|
||||
0, G_MAXLONG,
|
||||
False, XA_CARDINAL, &type, &format, &nitems,
|
||||
&bytes_after, &data);
|
||||
if (type == XA_CARDINAL)
|
||||
{
|
||||
prop = *(gulong *)data;
|
||||
XFree (data);
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_x11_screen_get_number_of_desktops:
|
||||
* @screen: a #GdkScreen
|
||||
*
|
||||
* Returns the number of workspaces for @screen when running under a
|
||||
* window manager that supports multiple workspaces, as described
|
||||
* in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
|
||||
* Window Manager Hints</ulink>.
|
||||
*
|
||||
* Returns: the number of workspaces, or 0 if workspaces are not supported
|
||||
*
|
||||
* Since: 3.10
|
||||
*/
|
||||
guint32
|
||||
gdk_x11_screen_get_number_of_desktops (GdkScreen *screen)
|
||||
{
|
||||
return get_netwm_cardinal_property (screen, "_NET_NUMBER_OF_DESKTOPS");
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_x11_screen_get_current_desktop:
|
||||
* @screen: a #GdkScreen
|
||||
*
|
||||
* Returns the current workspace for @screen when running under a
|
||||
* window manager that supports multiple workspaces, as described
|
||||
* in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
|
||||
* Window Manager Hints</ulink>.
|
||||
*
|
||||
* Returns: the current workspace, or 0 if workspaces are not supported
|
||||
*
|
||||
* Since: 3.10
|
||||
*/
|
||||
guint32
|
||||
gdk_x11_screen_get_current_desktop (GdkScreen *screen)
|
||||
{
|
||||
return get_netwm_cardinal_property (screen, "_NET_CURRENT_DESKTOP");
|
||||
}
|
||||
|
||||
@@ -2116,59 +2116,98 @@ gdk_x11_window_move_to_current_desktop (GdkWindow *window)
|
||||
static void
|
||||
move_to_current_desktop (GdkWindow *window)
|
||||
{
|
||||
if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
|
||||
gdk_atom_intern_static_string ("_NET_WM_DESKTOP")) &&
|
||||
gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
|
||||
gdk_atom_intern_static_string ("_NET_CURRENT_DESKTOP")))
|
||||
guint32 desktop;
|
||||
|
||||
desktop = gdk_x11_screen_get_current_desktop (GDK_WINDOW_SCREEN (window));
|
||||
gdk_x11_window_move_to_desktop (window, desktop);
|
||||
}
|
||||
|
||||
static guint32
|
||||
get_netwm_cardinal_property (GdkWindow *window,
|
||||
const gchar *name)
|
||||
{
|
||||
GdkScreen *screen = GDK_WINDOW_SCREEN (window);
|
||||
GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
|
||||
GdkAtom atom;
|
||||
guint32 prop = 0;
|
||||
Atom type;
|
||||
gint format;
|
||||
gulong nitems;
|
||||
gulong bytes_after;
|
||||
guchar *data;
|
||||
|
||||
atom = gdk_atom_intern_static_string (name);
|
||||
|
||||
if (!gdk_x11_screen_supports_net_wm_hint (screen, atom))
|
||||
return 0;
|
||||
|
||||
XGetWindowProperty (x11_screen->xdisplay,
|
||||
GDK_WINDOW_XID (window),
|
||||
gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), name),
|
||||
0, G_MAXLONG,
|
||||
False, XA_CARDINAL, &type, &format, &nitems,
|
||||
&bytes_after, &data);
|
||||
if (type == XA_CARDINAL)
|
||||
{
|
||||
Atom type;
|
||||
gint format;
|
||||
gulong nitems;
|
||||
gulong bytes_after;
|
||||
guchar *data;
|
||||
gulong *current_desktop;
|
||||
GdkDisplay *display;
|
||||
|
||||
display = gdk_window_get_display (window);
|
||||
|
||||
/* Get current desktop, then set it; this is a race, but not
|
||||
* one that matters much in practice.
|
||||
*/
|
||||
XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
|
||||
GDK_WINDOW_XROOTWIN (window),
|
||||
gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
|
||||
0, G_MAXLONG,
|
||||
False, XA_CARDINAL, &type, &format, &nitems,
|
||||
&bytes_after, &data);
|
||||
|
||||
if (type == XA_CARDINAL)
|
||||
{
|
||||
XClientMessageEvent xclient;
|
||||
current_desktop = (gulong *)data;
|
||||
|
||||
memset (&xclient, 0, sizeof (xclient));
|
||||
xclient.type = ClientMessage;
|
||||
xclient.serial = 0;
|
||||
xclient.send_event = True;
|
||||
xclient.window = GDK_WINDOW_XID (window);
|
||||
xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
|
||||
xclient.format = 32;
|
||||
|
||||
xclient.data.l[0] = *current_desktop;
|
||||
xclient.data.l[1] = 1; /* source indication */
|
||||
xclient.data.l[2] = 0;
|
||||
xclient.data.l[3] = 0;
|
||||
xclient.data.l[4] = 0;
|
||||
|
||||
XSendEvent (GDK_DISPLAY_XDISPLAY (display),
|
||||
GDK_WINDOW_XROOTWIN (window),
|
||||
False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask,
|
||||
(XEvent *)&xclient);
|
||||
|
||||
XFree (current_desktop);
|
||||
}
|
||||
prop = *(gulong *)data;
|
||||
XFree (data);
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
guint32
|
||||
gdk_x11_window_get_desktop (GdkWindow *window)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
|
||||
return get_netwm_cardinal_property (window, "_NET_WM_DESKTOP");
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_x11_window_move_to_desktop:
|
||||
* @window: a #GdkWindow
|
||||
* @desktop: the number of the workspace to move the window to
|
||||
*
|
||||
* Moves the window to the given workspace when running unde a
|
||||
* window manager that supports multiple workspaces, as described
|
||||
* in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
|
||||
* Window Manager Hints</ulink>.
|
||||
*
|
||||
* Since: 3.10
|
||||
*/
|
||||
void
|
||||
gdk_x11_window_move_to_desktop (GdkWindow *window,
|
||||
guint32 desktop)
|
||||
{
|
||||
GdkAtom atom;
|
||||
XClientMessageEvent xclient;
|
||||
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
|
||||
atom = gdk_atom_intern_static_string ("_NET_WM_DESKTOP");
|
||||
if (!gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window), atom))
|
||||
return;
|
||||
|
||||
memset (&xclient, 0, sizeof (xclient));
|
||||
xclient.type = ClientMessage;
|
||||
xclient.serial = 0;
|
||||
xclient.send_event = True;
|
||||
xclient.window = GDK_WINDOW_XID (window);
|
||||
xclient.message_type = gdk_x11_atom_to_xatom_for_display (GDK_WINDOW_DISPLAY (window), atom);
|
||||
xclient.format = 32;
|
||||
|
||||
xclient.data.l[0] = desktop;
|
||||
xclient.data.l[1] = 1; /* source indication */
|
||||
xclient.data.l[2] = 0;
|
||||
xclient.data.l[3] = 0;
|
||||
xclient.data.l[4] = 0;
|
||||
|
||||
XSendEvent (GDK_WINDOW_XDISPLAY (window),
|
||||
GDK_WINDOW_XROOTWIN (window),
|
||||
False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask,
|
||||
(XEvent *)&xclient);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -104,6 +104,11 @@ GDK_AVAILABLE_IN_ALL
|
||||
XID gdk_x11_screen_get_monitor_output (GdkScreen *screen,
|
||||
gint monitor_num);
|
||||
|
||||
GDK_AVAILABLE_IN_3_10
|
||||
guint32 gdk_x11_screen_get_number_of_desktops (GdkScreen *screen);
|
||||
GDK_AVAILABLE_IN_3_10
|
||||
guint32 gdk_x11_screen_get_current_desktop (GdkScreen *screen);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_X11_SCREEN_H__ */
|
||||
|
||||
@@ -77,6 +77,12 @@ void gdk_x11_window_set_hide_titlebar_when_maximized (GdkWindow *window,
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_x11_window_move_to_current_desktop (GdkWindow *window);
|
||||
|
||||
GDK_AVAILABLE_IN_3_10
|
||||
guint32 gdk_x11_window_get_desktop (GdkWindow *window);
|
||||
GDK_AVAILABLE_IN_3_10
|
||||
void gdk_x11_window_move_to_desktop (GdkWindow *window,
|
||||
guint32 desktop);
|
||||
|
||||
GDK_AVAILABLE_IN_3_8
|
||||
void gdk_x11_window_set_frame_sync_enabled (GdkWindow *window,
|
||||
gboolean frame_sync_enabled);
|
||||
|
||||
Reference in New Issue
Block a user