]> Pileus Git - ~andy/gtk/blob - gtk/gtkxembed.c
Make PLT-reduction work with gcc4, and don't include everything in
[~andy/gtk] / gtk / gtkxembed.c
1 /* GTK - The GIMP Toolkit
2  * gtkxembed.c: Utilities for the XEMBED protocol
3  * Copyright (C) 2001, 2003, Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <config.h>
22 #include "gtkmain.h"
23 #include "gtkprivate.h"
24 #include "gtkxembed.h"
25 #include "gtkalias.h"
26
27 typedef struct _GtkXEmbedMessage GtkXEmbedMessage;
28
29 struct _GtkXEmbedMessage
30 {
31   glong      message;
32   glong      detail;
33   glong      data1;
34   glong      data2;
35   guint32    time;
36 };
37
38 static GSList *current_messages;
39
40
41 /**
42  * _gtk_xembed_push_message:
43  * @xevent: a XEvent
44  * 
45  * Adds a client message to the stack of current XEMBED events.
46  **/
47 void
48 _gtk_xembed_push_message (XEvent *xevent)
49 {
50   GtkXEmbedMessage *message = g_new (GtkXEmbedMessage, 1);
51   
52   message->time = xevent->xclient.data.l[0];
53   message->message = xevent->xclient.data.l[1];
54   message->detail = xevent->xclient.data.l[2];
55   message->data1 = xevent->xclient.data.l[3];
56   message->data2 = xevent->xclient.data.l[4];
57
58   current_messages = g_slist_prepend (current_messages, message);
59 }
60
61 /**
62  * _gtk_xembed_pop_message:
63  * 
64  * Removes an event added with _gtk_xembed_push_message()
65  **/
66 void
67 _gtk_xembed_pop_message (void)
68 {
69   GtkXEmbedMessage *message = current_messages->data;
70   current_messages = g_slist_delete_link (current_messages, current_messages);
71
72   g_free (message);
73 }
74
75 /**
76  * _gtk_xembed_set_focus_wrapped:
77  * 
78  * Sets a flag indicating that the current focus sequence wrapped
79  * around to the beginning of the ultimate toplevel.
80  **/
81 void
82 _gtk_xembed_set_focus_wrapped (void)
83 {
84   GtkXEmbedMessage *message;
85   
86   g_return_if_fail (current_messages != NULL);
87   message = current_messages->data;
88   g_return_if_fail (message->message == XEMBED_FOCUS_PREV || message->message == XEMBED_FOCUS_NEXT);
89   
90   message->data1 |= XEMBED_FOCUS_WRAPAROUND;
91 }
92
93 /**
94  * _gtk_xembed_get_focus_wrapped:
95  * 
96  * Gets whether the current focus sequence has wrapped around
97  * to the beginning of the ultimate toplevel.
98  * 
99  * Return value: %TRUE if the focus sequence has wrapped around.
100  **/
101 gboolean
102 _gtk_xembed_get_focus_wrapped (void)
103 {
104   GtkXEmbedMessage *message;
105   
106   g_return_val_if_fail (current_messages != NULL, FALSE);
107   message = current_messages->data;
108
109   return (message->data1 & XEMBED_FOCUS_WRAPAROUND) != 0;
110 }
111
112 static guint32
113 gtk_xembed_get_time (void)
114 {
115   if (current_messages)
116     {
117       GtkXEmbedMessage *message = current_messages->data;
118       return message->time;
119     }
120   else
121     return gtk_get_current_event_time ();
122 }
123
124 /**
125  * _gtk_xembed_send_message:
126  * @recipient: window to which to send the window, or %NULL
127  *             in which case nothing will be sent
128  * @message:   type of message
129  * @detail:    detail field of message
130  * @data1:     data1 field of message
131  * @data2:     data2 field of message
132  * 
133  * Sends a generic XEMBED message to a particular window.
134  **/
135 void
136 _gtk_xembed_send_message (GdkWindow        *recipient,
137                           XEmbedMessageType message,
138                           glong             detail,
139                           glong             data1,
140                           glong             data2)
141 {
142   GdkDisplay *display;
143   XEvent xevent;
144
145   if (!recipient)
146     return;
147           
148   g_return_if_fail (GDK_IS_WINDOW (recipient));
149
150   display = gdk_drawable_get_display (recipient);
151   GTK_NOTE (PLUGSOCKET,
152             g_message ("Sending XEMBED message of type %d", message));
153
154   xevent.xclient.window = GDK_WINDOW_XWINDOW (recipient);
155   xevent.xclient.type = ClientMessage;
156   xevent.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED");
157   xevent.xclient.format = 32;
158   xevent.xclient.data.l[0] = gtk_xembed_get_time ();
159   xevent.xclient.data.l[1] = message;
160   xevent.xclient.data.l[2] = detail;
161   xevent.xclient.data.l[3] = data1;
162   xevent.xclient.data.l[4] = data2;
163
164   gdk_error_trap_push ();
165   XSendEvent (GDK_WINDOW_XDISPLAY(recipient),
166               GDK_WINDOW_XWINDOW (recipient),
167               False, NoEventMask, &xevent);
168   gdk_display_sync (display);
169   gdk_error_trap_pop ();
170 }
171
172 /**
173  * _gtk_xembed_send_focus_message:
174  * @recipient: window to which to send the window, or %NULL
175  *             in which case nothing will be sent
176  * @message:   type of message
177  * @detail:    detail field of message
178  * 
179  * Sends a XEMBED message for moving the focus along the focus
180  * chain to a window. The flags field that these messages share
181  * will be correctly filled in.
182  **/
183 void
184 _gtk_xembed_send_focus_message (GdkWindow        *recipient,
185                                 XEmbedMessageType message,
186                                 glong             detail)
187 {
188   gulong flags = 0;
189
190   if (!recipient)
191     return;
192   
193   g_return_if_fail (GDK_IS_WINDOW (recipient));
194   g_return_if_fail (message == XEMBED_FOCUS_IN ||
195                     message == XEMBED_FOCUS_NEXT ||
196                     message == XEMBED_FOCUS_PREV);
197                     
198   if (current_messages)
199     {
200       GtkXEmbedMessage *message = current_messages->data;
201       switch (message->message)
202         {
203         case XEMBED_FOCUS_IN:
204         case XEMBED_FOCUS_NEXT:
205         case XEMBED_FOCUS_PREV:
206           flags = message->data1 & XEMBED_FOCUS_WRAPAROUND;
207           break;
208         default:
209           break;
210         }
211     }
212
213   _gtk_xembed_send_message (recipient, message, detail, flags, 0);
214 }
215