1 /* Sticky Notes
2  * Copyright (C) 2002-2003 Loban A Rahman
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2, or (at your option)
7  * any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19 
20 #include <config.h>
21 #include "util.h"
22 
23 #include <X11/Xlib.h>
24 #include <X11/Xatom.h>
25 #include <gdk/gdk.h>
26 #include <gdk/gdkx.h>
27 #include <gtk/gtk.h>
28 
29 static Atom
xstuff_atom_get(const char * atom_name)30 xstuff_atom_get (const char *atom_name)
31 {
32     static GHashTable *atom_hash;
33     Display           *xdisplay;
34     Atom               retval;
35 
36     g_return_val_if_fail (atom_name != NULL, None);
37 
38     xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
39 
40     if (!atom_hash)
41         atom_hash = g_hash_table_new_full (g_str_hash,
42                                            g_str_equal,
43                                            g_free, NULL);
44 
45     retval = GPOINTER_TO_UINT (g_hash_table_lookup (atom_hash, atom_name));
46     if (!retval) {
47         retval = XInternAtom (xdisplay, atom_name, FALSE);
48 
49         if (retval != None)
50             g_hash_table_insert (atom_hash, g_strdup (atom_name),
51                                  GUINT_TO_POINTER (retval));
52     }
53 
54     return retval;
55 }
56 
57 int
xstuff_get_current_workspace(GtkWindow * window)58 xstuff_get_current_workspace (GtkWindow *window)
59 {
60     Window      root_window;
61     Atom        type = None;
62     gulong      nitems;
63     gulong      bytes_after;
64     gulong     *num;
65     int         format;
66     int         result;
67     int         retval;
68     GdkDisplay *gdk_display;
69     Display    *xdisplay;
70 
71     root_window = GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (window)));
72     gdk_display = gdk_display_get_default ();
73     xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display);
74 
75     gdk_x11_display_error_trap_push (gdk_display);
76     result = XGetWindowProperty (xdisplay,
77                                  root_window,
78                                  xstuff_atom_get ("_NET_CURRENT_DESKTOP"),
79                                  0, G_MAXLONG,
80                                  False, XA_CARDINAL,
81                                  &type, &format, &nitems,
82                                  &bytes_after, (gpointer) &num);
83     if (gdk_x11_display_error_trap_pop (gdk_display) || result != Success)
84         return -1;
85 
86     if (type != XA_CARDINAL) {
87         XFree (num);
88         return -1;
89     }
90 
91     retval = *num;
92 
93     XFree (num);
94 
95     return retval;
96 }
97 void
xstuff_change_workspace(GtkWindow * window,int new_space)98 xstuff_change_workspace (GtkWindow *window,
99                          int        new_space)
100 {
101     XEvent xev;
102     Window xwindow;
103     Display *gdk_display;
104     Screen *screen;
105 
106     gdk_display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
107     xwindow = GDK_WINDOW_XID (GDK_WINDOW (gtk_widget_get_window (GTK_WIDGET (window))));
108     screen = GDK_SCREEN_XSCREEN (gtk_widget_get_screen (GTK_WIDGET (window)));
109 
110     xev.xclient.type = ClientMessage;
111     xev.xclient.serial = 0;
112     xev.xclient.send_event = True;
113     xev.xclient.display = gdk_display;
114     xev.xclient.window = xwindow;
115     xev.xclient.message_type = xstuff_atom_get ("_NET_WM_DESKTOP");
116     xev.xclient.format = 32;
117     xev.xclient.data.l[0] = new_space;
118     xev.xclient.data.l[1] = 0;
119     xev.xclient.data.l[2] = 0;
120 
121     XSendEvent (gdk_display,
122                 RootWindowOfScreen (screen),
123                 False,
124                 SubstructureRedirectMask | SubstructureNotifyMask,
125                 &xev);
126 }
127