#include <X11/Xatom.h>
typedef struct _GdkIOClosure GdkIOClosure;
-typedef struct _GdkEventPrivate GdkEventPrivate;
typedef struct _GdkDisplaySource GdkDisplaySource;
#define DOUBLE_CLICK_TIME 250
#define DOUBLE_CLICK_DIST 5
#define TRIPLE_CLICK_DIST 5
-typedef enum
-{
- /* Following flag is set for events on the event queue during
- * translation and cleared afterwards.
- */
- GDK_EVENT_PENDING = 1 << 0
-} GdkEventFlags;
-
struct _GdkIOClosure
{
GdkInputFunction function;
gpointer data;
};
-struct _GdkEventPrivate
-{
- GdkEvent event;
- guint flags;
-};
-
struct _GdkDisplaySource
{
GSource source;
_gdk_x11_events_init_screen (GdkScreen *screen)
{
GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
-
+
+ /* Keep a flag to avoid extra notifies that we don't need
+ */
+ screen_x11->xsettings_in_init = TRUE;
screen_x11->xsettings_client = xsettings_client_new (screen_x11->xdisplay,
screen_x11->screen_num,
gdk_xsettings_notify_cb,
gdk_xsettings_watch_cb,
screen);
+ screen_x11->xsettings_in_init = FALSE;
+}
+
+void
+_gdk_x11_events_uninit_screen (GdkScreen *screen)
+{
+ GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
+
+ xsettings_client_destroy (screen_x11->xsettings_client);
+ screen_x11->xsettings_client = NULL;
}
void
GDK_NOTE (MISC, g_message ("connection number: %d", connection_number));
- source = gdk_display_source_new (display);
+ source = display_x11->event_source = gdk_display_source_new (display);
display_source = (GdkDisplaySource*) source;
g_source_set_priority (source, GDK_PRIORITY_EVENTS);
gdk_atom_intern ("WM_PROTOCOLS", FALSE),
gdk_wm_protocols_filter,
NULL);
-
- _gdk_x11_events_init_screen (display_x11->default_screen);
}
if (xevent.xany.type == GraphicsExpose)
{
- event = _gdk_event_new ();
+ event = gdk_event_new (GDK_NOTHING);
if (gdk_event_translate (GDK_WINDOW_DISPLAY (window), event,
&xevent, TRUE))
*
* Adds a filter to be called when X ClientMessage events are received.
*
+ * Since: 2.2
**/
void
gdk_display_add_client_message_filter (GdkDisplay *display,
GdkFilterFunc func,
gpointer data)
{
- gdk_display_add_client_message_filter (gdk_get_default_display (),
+ gdk_display_add_client_message_filter (gdk_display_get_default (),
message_type, func, data);
}
gulong bytes_after;
Atom *atoms = NULL;
gulong i;
- gboolean found_sticky, found_maxvert, found_maxhorz;
+ gboolean found_sticky, found_maxvert, found_maxhorz, found_fullscreen;
GdkWindowState old_state;
GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ gdk_window_get_window_type (window) != GDK_WINDOW_TOPLEVEL)
return;
found_sticky = FALSE;
found_maxvert = FALSE;
found_maxhorz = FALSE;
+ found_fullscreen = FALSE;
XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
Atom sticky_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_STICKY");
Atom maxvert_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT");
Atom maxhorz_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ");
-
+ Atom fullscreen_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_FULLSCREEN");
+
i = 0;
while (i < nitems)
{
found_maxvert = TRUE;
else if (atoms[i] == maxhorz_atom)
found_maxhorz = TRUE;
-
+ else if (atoms[i] == fullscreen_atom)
+ found_fullscreen = TRUE;
+
++i;
}
GDK_WINDOW_STATE_STICKY);
}
+ if (old_state & GDK_WINDOW_STATE_FULLSCREEN)
+ {
+ if (!found_fullscreen)
+ gdk_synthesize_window_state (window,
+ GDK_WINDOW_STATE_FULLSCREEN,
+ 0);
+ }
+ else
+ {
+ if (found_fullscreen)
+ gdk_synthesize_window_state (window,
+ 0,
+ GDK_WINDOW_STATE_FULLSCREEN);
+ }
+
/* Our "maximized" means both vertical and horizontal; if only one,
* we don't expose that via GDK
*/
gdk_event_put (&event);
}
+static void
+set_screen_from_root (GdkDisplay *display,
+ GdkEvent *event,
+ Window xrootwin)
+{
+ GdkScreen *screen;
+
+ screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
+ g_assert (screen);
+
+ gdk_event_set_screen (event, screen);
+}
+
+static void
+translate_key_event (GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent)
+{
+ GdkKeymap *keymap = gdk_keymap_get_for_display (display);
+ gunichar c = 0;
+ guchar buf[7];
+
+ event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
+ event->key.time = xevent->xkey.time;
+
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+ event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
+ event->key.hardware_keycode = xevent->xkey.keycode;
+
+ event->key.keyval = GDK_VoidSymbol;
+
+ gdk_keymap_translate_keyboard_state (keymap,
+ event->key.hardware_keycode,
+ event->key.state,
+ event->key.group,
+ &event->key.keyval,
+ NULL, NULL, NULL);
+
+ /* Fill in event->string crudely, since various programs
+ * depend on it.
+ */
+ event->key.string = NULL;
+
+ if (event->key.keyval != GDK_VoidSymbol)
+ c = gdk_keyval_to_unicode (event->key.keyval);
+
+ if (c)
+ {
+ gsize bytes_written;
+ gint len;
+
+ /* Apply the control key - Taken from Xlib
+ */
+ if (event->key.state & GDK_CONTROL_MASK)
+ {
+ if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
+ else if (c == '2')
+ {
+ event->key.string = g_memdup ("\0\0", 2);
+ event->key.length = 1;
+ buf[0] = '\0';
+ goto out;
+ }
+ else if (c >= '3' && c <= '7') c -= ('3' - '\033');
+ else if (c == '8') c = '\177';
+ else if (c == '/') c = '_' & 0x1F;
+ }
+
+ len = g_unichar_to_utf8 (c, buf);
+ buf[len] = '\0';
+
+ event->key.string = g_locale_from_utf8 (buf, len,
+ NULL, &bytes_written,
+ NULL);
+ if (event->key.string)
+ event->key.length = bytes_written;
+ }
+ else if (event->key.keyval == GDK_Escape)
+ {
+ event->key.length = 1;
+ event->key.string = g_strdup ("\033");
+ }
+ else if (event->key.keyval == GDK_Return ||
+ event->key.keyval == GDK_KP_Enter)
+ {
+ event->key.length = 1;
+ event->key.string = g_strdup ("\r");
+ }
+
+ if (!event->key.string)
+ {
+ event->key.length = 0;
+ event->key.string = g_strdup ("");
+ }
+
+ out:
+#ifdef G_ENABLE_DEBUG
+ if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
+ {
+ g_message ("%s:\t\twindow: %ld key: %12s %d",
+ event->type == GDK_KEY_PRESS ? "key press " : "key release",
+ xevent->xkey.window,
+ event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
+ event->key.keyval);
+
+ if (event->key.length > 0)
+ g_message ("\t\tlength: %4d string: \"%s\"",
+ event->key.length, buf);
+ }
+#endif /* G_ENABLE_DEBUG */
+}
+
+/* Return the window this has to do with, if any, rather
+ * than the frame or root window that was selecting
+ * for substructure
+ */
+static Window
+get_real_window (XEvent *event)
+{
+ switch (event->type)
+ {
+ case CreateNotify:
+ return event->xcreatewindow.window;
+
+ case DestroyNotify:
+ return event->xdestroywindow.window;
+
+ case UnmapNotify:
+ return event->xunmap.window;
+
+ case MapNotify:
+ return event->xmap.window;
+
+ case MapRequest:
+ return event->xmaprequest.window;
+
+ case ReparentNotify:
+ return event->xreparent.window;
+
+ case ConfigureNotify:
+ return event->xconfigure.window;
+
+ case ConfigureRequest:
+ return event->xconfigurerequest.window;
+
+ case GravityNotify:
+ return event->xgravity.window;
+
+ case CirculateNotify:
+ return event->xcirculate.window;
+
+ case CirculateRequest:
+ return event->xcirculaterequest.window;
+
+ default:
+ return event->xany.window;
+ }
+}
+
+#ifdef G_ENABLE_DEBUG
+static const char notify_modes[][18] = {
+ "NotifyNormal",
+ "NotifyGrab",
+ "NotifyUngrab",
+ "NotifyWhileGrabbed"
+};
+
+static const char notify_details[][22] = {
+ "NotifyAncestor",
+ "NotifyVirtual",
+ "NotifyInferior",
+ "NotifyNonlinear",
+ "NotifyNonlinearVirtual",
+ "NotifyPointer",
+ "NotifyPointerRoot",
+ "NotifyDetailNone"
+};
+#endif
+
static gboolean
gdk_event_translate (GdkDisplay *display,
GdkEvent *event,
GdkWindow *window;
GdkWindowObject *window_private;
GdkWindowImplX11 *window_impl = NULL;
- static XComposeStatus compose;
- KeySym keysym;
- int charcount;
- char buf[16];
gint return_val;
gint xoffset, yoffset;
GdkScreen *screen = NULL;
GdkScreenX11 *screen_x11 = NULL;
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+ Window xwindow;
return_val = FALSE;
window = NULL;
window_private = NULL;
event->any.window = NULL;
-
+
if (_gdk_default_filters)
{
/* Apply global filters */
return_val = FALSE;
}
- /* Find the GdkWindow that this event occurred in. */
+ /* Find the GdkWindow that this event relates to.
+ * Basically this means substructure events
+ * are reported same as structure events
+ */
+ xwindow = get_real_window (xevent);
- window = gdk_window_lookup_for_display (display, xevent->xany.window);
+ window = gdk_window_lookup_for_display (display, xwindow);
window_private = (GdkWindowObject *) window;
if (window)
if (GDK_IS_WINDOW (window))
{
window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
-
- if (xevent->xany.window != GDK_WINDOW_XID (window))
+
+ /* Move key events on focus window to the real toplevel, and
+ * filter out all other events on focus window
+ */
+ if (xwindow == window_impl->focus_window)
{
- g_assert (xevent->xany.window == window_impl->focus_window);
-
switch (xevent->type)
{
case KeyPress:
case KeyRelease:
- xevent->xany.window = GDK_WINDOW_XID (window);
+ xwindow = GDK_WINDOW_XID (window);
+ xevent->xany.window = xwindow;
break;
default:
return FALSE;
}
}
- g_object_ref (G_OBJECT (window));
+ g_object_ref (window);
}
event->any.window = window;
}
if (screen_x11 && screen_x11->wmspec_check_window != None &&
- xevent->xany.window == screen_x11->wmspec_check_window)
+ xwindow == screen_x11->wmspec_check_window)
{
if (xevent->type == DestroyNotify)
- screen_x11->wmspec_check_window = None;
+ {
+ screen_x11->wmspec_check_window = None;
+ g_free (screen_x11->window_manager_name);
+ screen_x11->window_manager_name = g_strdup ("unknown");
+
+ /* careful, reentrancy */
+ _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
+ }
/* Eat events on this window unless someone had wrapped
* it as a foreign window
xoffset = 0;
yoffset = 0;
}
-
+
switch (xevent->type)
{
case KeyPress:
return_val = FALSE;
break;
}
-
- /* Lookup the string corresponding to the given keysym.
- */
-
- charcount = XLookupString (&xevent->xkey, buf, 16,
- &keysym, &compose);
- event->key.keyval = keysym;
- event->key.hardware_keycode = xevent->xkey.keycode;
-
- if (charcount > 0 && buf[charcount-1] == '\0')
- charcount --;
- else
- buf[charcount] = '\0';
-
-#ifdef G_ENABLE_DEBUG
- if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
- {
- g_message ("key press:\twindow: %ld key: %12s %d",
- xevent->xkey.window,
- event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
- event->key.keyval);
- if (charcount > 0)
- g_message ("\t\tlength: %4d string: \"%s\"",
- charcount, buf);
- }
-#endif /* G_ENABLE_DEBUG */
-
- event->key.type = GDK_KEY_PRESS;
- event->key.window = window;
- event->key.time = xevent->xkey.time;
- event->key.state = (GdkModifierType) xevent->xkey.state;
- event->key.string = g_strdup (buf);
- event->key.length = charcount;
-
- /* bits 13 and 14 in the "state" field are the keyboard group */
-#define KEYBOARD_GROUP_SHIFT 13
-#define KEYBOARD_GROUP_MASK ((1 << 13) | (1 << 14))
-
- event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
-
+ translate_key_event (display, event, xevent);
break;
-
+
case KeyRelease:
if (window_private == NULL)
{
break;
}
- /* Lookup the string corresponding to the given keysym.
- */
-
/* Emulate detectable auto-repeat by checking to see
* if the next event is a key press with the same
* keycode and timestamp, and if so, ignoring the event.
if (next_event.type == KeyPress &&
next_event.xkey.keycode == xevent->xkey.keycode &&
next_event.xkey.time == xevent->xkey.time)
- break;
+ {
+ return_val = FALSE;
+ break;
+ }
}
-
- keysym = GDK_VoidSymbol;
- charcount = XLookupString (&xevent->xkey, buf, 16,
- &keysym, &compose);
- event->key.keyval = keysym;
-
- GDK_NOTE (EVENTS,
- g_message ("key release:\t\twindow: %ld key: %12s %d",
- xevent->xkey.window,
- XKeysymToString (event->key.keyval),
- event->key.keyval));
-
- event->key.type = GDK_KEY_RELEASE;
- event->key.window = window;
- event->key.time = xevent->xkey.time;
- event->key.state = (GdkModifierType) xevent->xkey.state;
- event->key.length = 0;
- event->key.string = NULL;
-
- event->key.group = (xevent->xkey.state & KEYBOARD_GROUP_MASK) >> KEYBOARD_GROUP_SHIFT;
+ translate_key_event (display, event, xevent);
break;
case ButtonPress:
event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
event->scroll.state = (GdkModifierType) xevent->xbutton.state;
- event->scroll.device = _gdk_core_pointer;
+ event->scroll.device = display->core_pointer;
+
+ set_screen_from_root (display, event, xevent->xbutton.root);
+
break;
default:
event->button.axes = NULL;
event->button.state = (GdkModifierType) xevent->xbutton.state;
event->button.button = xevent->xbutton.button;
- event->button.device = _gdk_core_pointer;
+ event->button.device = display->core_pointer;
+ set_screen_from_root (display, event, xevent->xbutton.root);
+
_gdk_event_button_generate (display, event);
break;
}
event->button.axes = NULL;
event->button.state = (GdkModifierType) xevent->xbutton.state;
event->button.button = xevent->xbutton.button;
- event->button.device = _gdk_core_pointer;
+ event->button.device = display->core_pointer;
+
+ set_screen_from_root (display, event, xevent->xbutton.root);
break;
event->motion.axes = NULL;
event->motion.state = (GdkModifierType) xevent->xmotion.state;
event->motion.is_hint = xevent->xmotion.is_hint;
- event->motion.device = _gdk_core_pointer;
+ event->motion.device = display->core_pointer;
+
+ set_screen_from_root (display, event, xevent->xmotion.root);
break;
if (window &&
GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
xevent->xcrossing.detail != NotifyInferior &&
- xevent->xcrossing.focus && !window_impl->has_focus)
+ xevent->xcrossing.focus && !window_impl->has_focus_window)
{
gboolean had_focus = HAS_FOCUS (window_impl);
-
+
window_impl->has_pointer_focus = TRUE;
if (HAS_FOCUS (window_impl) != had_focus)
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
+ set_screen_from_root (display, event, xevent->xcrossing.root);
+
/* Translate the crossing mode into Gdk terms.
*/
switch (xevent->xcrossing.mode)
if (window &&
GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
xevent->xcrossing.detail != NotifyInferior &&
- xevent->xcrossing.focus && !window_impl->has_focus)
+ xevent->xcrossing.focus && !window_impl->has_focus_window)
{
gboolean had_focus = HAS_FOCUS (window_impl);
window_impl->has_pointer_focus = FALSE;
-
+
if (HAS_FOCUS (window_impl) != had_focus)
generate_focus_event (window, FALSE);
}
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
+ set_screen_from_root (display, event, xevent->xcrossing.root);
+
/* Translate the crossing mode into Gdk terms.
*/
switch (xevent->xcrossing.mode)
*/
case FocusIn:
GDK_NOTE (EVENTS,
- g_message ("focus in:\t\twindow: %ld", xevent->xfocus.window));
+ g_message ("focus in:\t\twindow: %ld, detail: %s, mode: %s",
+ xevent->xfocus.window,
+ notify_details[xevent->xfocus.detail],
+ notify_modes[xevent->xfocus.mode]));
if (window && GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
{
case NotifyNonlinear:
case NotifyVirtual:
case NotifyNonlinearVirtual:
- window_impl->has_focus = TRUE;
+ window_impl->has_focus_window = TRUE;
+ /* We pretend that the focus moves to the grab
+ * window, so we pay attention to NotifyGrab
+ * NotifyUngrab, and ignore NotifyWhileGrabbed
+ */
+ if (xevent->xfocus.mode != NotifyWhileGrabbed)
+ window_impl->has_focus = TRUE;
break;
case NotifyPointer:
- window_impl->has_pointer_focus = TRUE;
+ /* The X server sends NotifyPointer/NotifyGrab,
+ * but the pointer focus is ignored while a
+ * grab is in effect
+ */
+ if (xevent->xfocus.mode != NotifyGrab)
+ window_impl->has_pointer_focus = TRUE;
break;
case NotifyInferior:
case NotifyPointerRoot:
break;
case FocusOut:
GDK_NOTE (EVENTS,
- g_message ("focus out:\t\twindow: %ld", xevent->xfocus.window));
-
+ g_message ("focus out:\t\twindow: %ld, detail: %s, mode: %s",
+ xevent->xfocus.window,
+ notify_details[xevent->xfocus.detail],
+ notify_modes[xevent->xfocus.mode]));
+
if (window && GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
{
gboolean had_focus = HAS_FOCUS (window_impl);
case NotifyNonlinear:
case NotifyVirtual:
case NotifyNonlinearVirtual:
- window_impl->has_focus = FALSE;
+ window_impl->has_focus_window = FALSE;
+ if (xevent->xfocus.mode != NotifyWhileGrabbed)
+ window_impl->has_focus = FALSE;
break;
case NotifyPointer:
- window_impl->has_pointer_focus = FALSE;
+ if (xevent->xfocus.mode != NotifyUngrab)
+ window_impl->has_pointer_focus = FALSE;
break;
case NotifyInferior:
case NotifyPointerRoot:
? " (discarding)"
: GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD
? " (discarding child)"
+ : xevent->xconfigure.event != xevent->xconfigure.window
+ ? " (discarding substructure)"
: ""));
+ if (window && GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
+ _gdk_x11_screen_size_changed (screen, xevent);
+
if (window &&
+ xevent->xconfigure.event == xevent->xconfigure.window &&
!GDK_WINDOW_DESTROYED (window) &&
(window_private->extension_events != 0))
_gdk_input_configure_event (&xevent->xconfigure, window);
if (!window ||
+ xevent->xconfigure.event != xevent->xconfigure.window ||
GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
return_val = FALSE;
if (window_private == NULL)
{
- return_val = FALSE;
+ return_val = FALSE;
break;
}
- event->property.type = GDK_PROPERTY_NOTIFY;
- event->property.window = window;
- event->property.atom = gdk_x11_xatom_to_atom_for_display (display, xevent->xproperty.atom);
- event->property.time = xevent->xproperty.time;
- event->property.state = xevent->xproperty.state;
-
if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE") ||
xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"))
{
/* If window state changed, then synthesize those events. */
- gdk_check_wm_state_changed (event->property.window);
+ gdk_check_wm_state_changed (window);
}
+ if (window_private->event_mask & GDK_PROPERTY_CHANGE_MASK)
+ {
+ event->property.type = GDK_PROPERTY_NOTIFY;
+ event->property.window = window;
+ event->property.atom = gdk_x11_xatom_to_atom_for_display (display, xevent->xproperty.atom);
+ event->property.time = xevent->xproperty.time;
+ event->property.state = xevent->xproperty.state;
+ }
+ else
+ return_val = FALSE;
+
break;
case SelectionClear:
/* Let XLib know that there is a new keyboard mapping.
*/
XRefreshKeyboardMapping (&xevent->xmapping);
- ++display_x11->keymap_serial;
+ _gdk_keymap_keys_changed (display);
return_val = FALSE;
break;
switch (xkb_event->any.xkb_type)
{
case XkbMapNotify:
- ++display_x11->keymap_serial;
+ _gdk_keymap_keys_changed (display);
return_val = FALSE;
break;
if (return_val)
{
if (event->any.window)
- gdk_window_ref (event->any.window);
+ g_object_ref (event->any.window);
if (((event->any.type == GDK_ENTER_NOTIFY) ||
(event->any.type == GDK_LEAVE_NOTIFY)) &&
(event->crossing.subwindow != NULL))
- gdk_window_ref (event->crossing.subwindow);
+ g_object_ref (event->crossing.subwindow);
}
else
{
}
if (window)
- gdk_window_unref (window);
+ g_object_unref (window);
return return_val;
}
continue;
}
- event = _gdk_event_new ();
+ event = gdk_event_new (GDK_NOTHING);
- event->any.type = GDK_NOTHING;
event->any.window = NULL;
event->any.send_event = xevent.xany.send_event ? TRUE : FALSE;
}
/**
- * gdk_event_send_client_message:
+ * gdk_event_send_client_message_for_display:
+ * @display: the #GdkDisplay for the window where the message is to be sent.
* @event: the #GdkEvent to send, which should be a #GdkEventClient.
- * @xid: the window to send the X ClientMessage event to.
- *
- * Sends an X ClientMessage event to a given window (which must be
- * on the default #GdkDisplay.)
- * This could be used for communicating between different applications,
- * though the amount of data is limited to 20 bytes.
- *
- * Return value: non-zero on success.
- **/
-gboolean
-gdk_event_send_client_message (GdkEvent *event, guint32 xid)
-{
- g_return_val_if_fail (event != NULL, FALSE);
-
- return gdk_event_send_client_message_for_display (gdk_get_default_display (),
- event, xid);
-}
-
-/**
- * gdk_event_send_client_message_for_display :
- * @display : the #GdkDisplay for the window where the message is to be sent.
- * @event : the #GdkEvent to send, which should be a #GdkEventClient.
- * @xid : the X window to send the X ClientMessage event to.
+ * @winid: the window to send the X ClientMessage event to.
*
* Sends an X ClientMessage event to a given window.
*
* This could be used for communicating between different applications,
* though the amount of data is limited to 20 bytes.
*
- * Returns : non-zero on success.
+ * Returns: non-zero on success.
+ *
+ * Since: 2.2
*/
gboolean
-gdk_event_send_client_message_for_display (GdkDisplay *display,
- GdkEvent *event,
- guint32 xid)
+gdk_event_send_client_message_for_display (GdkDisplay *display,
+ GdkEvent *event,
+ GdkNativeWindow winid)
{
XEvent sev;
sev.xclient.type = ClientMessage;
sev.xclient.display = GDK_DISPLAY_XDISPLAY (display);
sev.xclient.format = event->client.data_format;
- sev.xclient.window = xid;
+ sev.xclient.window = winid;
memcpy(&sev.xclient.data, &event->client.data, sizeof (sev.xclient.data));
sev.xclient.message_type = gdk_x11_atom_to_xatom_for_display (display, event->client.message_type);
- return _gdk_send_xevent (display, xid, False, NoEventMask, &sev);
+ return _gdk_send_xevent (display, winid, False, NoEventMask, &sev);
}
return result;
}
-/**
- * gdk_event_send_clientmessage_toall:
- * @event: the #GdkEvent to send, which should be a #GdkEventClient.
- *
- * Sends an X ClientMessage event to all toplevel windows on the default
- * #GdkScreen.
- *
- * Toplevel windows are determined by checking for the WM_STATE property, as
- * described in the Inter-Client Communication Conventions Manual (ICCCM).
- * If no windows are found with the WM_STATE property set, the message is sent
- * to all children of the root window.
- **/
-void
-gdk_event_send_clientmessage_toall (GdkEvent *event)
-{
- g_return_if_fail (event != NULL);
-
- gdk_screen_broadcast_client_message (gdk_get_default_screen (), event);
-}
-
/**
* gdk_screen_broadcast_client_message:
- * @screen : the #GdkScreen where the event will be broadcasted.
- * @event : the #GdkEvent.
+ * @screen: the #GdkScreen where the event will be broadcasted.
+ * @event: the #GdkEvent.
*
* Sends an X ClientMessage event to all toplevel windows on @screen.
*
* as described in the Inter-Client Communication Conventions Manual (ICCCM).
* If no windows are found with the WM_STATE property set, the message is
* sent to all children of the root window.
+ *
+ * Since: 2.2
*/
void
return xevent.xproperty.time;
}
+static void
+fetch_net_wm_check_window (GdkScreen *screen)
+{
+ GdkScreenX11 *screen_x11;
+ GdkDisplay *display;
+ Atom type;
+ gint format;
+ gulong n_items;
+ gulong bytes_after;
+ Window *xwindow;
+
+ /* This function is very slow on every call if you are not running a
+ * spec-supporting WM. For now not optimized, because it isn't in
+ * any critical code paths, but if you used it somewhere that had to
+ * be fast you want to avoid "GTK is slow with old WMs" complaints.
+ * Probably at that point the function should be changed to query
+ * _NET_SUPPORTING_WM_CHECK only once every 10 seconds or something.
+ */
+
+ screen_x11 = GDK_SCREEN_X11 (screen);
+ display = screen_x11->display;
+
+ if (screen_x11->wmspec_check_window != None)
+ return; /* already have it */
+
+ XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window,
+ gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTING_WM_CHECK"),
+ 0, G_MAXLONG, False, XA_WINDOW, &type, &format,
+ &n_items, &bytes_after, (guchar **) & xwindow);
+
+ if (type != XA_WINDOW)
+ return;
+
+ gdk_error_trap_push ();
+
+ /* Find out if this WM goes away, so we can reset everything. */
+ XSelectInput (screen_x11->xdisplay, *xwindow, StructureNotifyMask);
+
+ screen_x11->wmspec_check_window = *xwindow;
+ XFree (xwindow);
+
+ screen_x11->need_refetch_net_supported = TRUE;
+ screen_x11->need_refetch_wm_name = TRUE;
+
+ /* Careful, reentrancy */
+ _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
+}
+
+/**
+ * gdk_x11_screen_get_window_manager_name:
+ * @screen: a #GdkScreen
+ *
+ * Returns the name of the window manager for @screen.
+ *
+ * Return value: the name of the window manager screen @screen, or
+ * "unknown" if the window manager is unknown. The string is owned by GDK
+ * and should not be freed.
+ *
+ * Since: 2.2
+ **/
+const char*
+gdk_x11_screen_get_window_manager_name (GdkScreen *screen)
+{
+ GdkScreenX11 *screen_x11;
+
+ screen_x11 = GDK_SCREEN_X11 (screen);
+
+ fetch_net_wm_check_window (screen);
+
+ if (screen_x11->need_refetch_wm_name)
+ {
+ /* Get the name of the window manager */
+ screen_x11->need_refetch_wm_name = FALSE;
+
+ g_free (screen_x11->window_manager_name);
+ screen_x11->window_manager_name = g_strdup ("unknown");
+
+ if (screen_x11->wmspec_check_window != None)
+ {
+ Atom type;
+ gint format;
+ gulong n_items;
+ gulong bytes_after;
+ guchar *name;
+
+ name = NULL;
+
+ XGetWindowProperty (GDK_DISPLAY_XDISPLAY (screen_x11->display),
+ screen_x11->wmspec_check_window,
+ gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
+ "_NET_WM_NAME"),
+ 0, G_MAXLONG, False,
+ gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
+ "UTF8_STRING"),
+ &type, &format,
+ &n_items, &bytes_after,
+ (guchar **)&name);
+
+ gdk_display_sync (screen_x11->display);
+
+ gdk_error_trap_pop ();
+
+ if (name != NULL)
+ {
+ g_free (screen_x11->window_manager_name);
+ screen_x11->window_manager_name = g_strdup (name);
+ XFree (name);
+ }
+ }
+ }
+
+ return GDK_SCREEN_X11 (screen)->window_manager_name;
+}
+
typedef struct _NetWmSupportedAtoms NetWmSupportedAtoms;
struct _NetWmSupportedAtoms
/**
* gdk_x11_screen_supports_net_wm_hint:
- * @screen : the relevant #GdkScreen.
+ * @screen: the relevant #GdkScreen.
* @property: a property atom.
*
* This function is specific to the X11 backend of GDK, and indicates
* whether the window manager supports a certain hint from the
* Extended Window Manager Hints Specification. You can find this
- * specification on http://www.freedesktop.org.
+ * specification on
+ * <ulink url="http://www.freedesktop.org">http://www.freedesktop.org</ulink>.
*
* When using this function, keep in mind that the window manager
* can change over time; so you shouldn't use this function in
* is that your application can start up before the window manager
* does when the user logs in, and before the window manager starts
* gdk_x11_screen_supports_net_wm_hint() will return %FALSE for every property.
+ * You can monitor the window_manager_changed signal on #GdkScreen to detect
+ * a window manager change.
*
* Return value: %TRUE if the window manager supports @property
+ *
+ * Since: 2.2
**/
gboolean
gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen,
GdkAtom property)
{
- Atom type;
- gint format;
- gulong nitems;
- gulong bytes_after;
- Window *xwindow;
gulong i;
GdkScreenX11 *screen_x11;
NetWmSupportedAtoms *supported_atoms;
if (!supported_atoms)
{
supported_atoms = g_new0 (NetWmSupportedAtoms, 1);
- g_object_set_data (G_OBJECT (screen), "net-wm-supported-atoms", supported_atoms);
+ g_object_set_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms", supported_atoms);
}
- if (screen_x11->wmspec_check_window != None)
+ fetch_net_wm_check_window (screen);
+
+ if (screen_x11->wmspec_check_window == None)
+ return FALSE;
+
+ if (screen_x11->need_refetch_net_supported)
{
- if (supported_atoms->atoms == NULL)
- return FALSE;
+ /* WM has changed since we last got the supported list,
+ * refetch it.
+ */
+ Atom type;
+ gint format;
+ gulong bytes_after;
+
+ screen_x11->need_refetch_net_supported = FALSE;
- i = 0;
- while (i < supported_atoms->n_atoms)
- {
- if (supported_atoms->atoms[i] == gdk_x11_atom_to_xatom_for_display (display, property))
- return TRUE;
-
- ++i;
- }
+ if (supported_atoms->atoms)
+ XFree (supported_atoms->atoms);
- return FALSE;
+ supported_atoms->atoms = NULL;
+ supported_atoms->n_atoms = 0;
+
+ XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window,
+ gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTED"),
+ 0, G_MAXLONG, False, XA_ATOM, &type, &format,
+ &supported_atoms->n_atoms, &bytes_after,
+ (guchar **)&supported_atoms->atoms);
+
+ if (type != XA_ATOM)
+ return FALSE;
}
-
- if (supported_atoms->atoms)
- XFree (supported_atoms->atoms);
-
- supported_atoms->atoms = NULL;
- supported_atoms->n_atoms = 0;
-
- /* This function is very slow on every call if you are not running a
- * spec-supporting WM. For now not optimized, because it isn't in
- * any critical code paths, but if you used it somewhere that had to
- * be fast you want to avoid "GTK is slow with old WMs" complaints.
- * Probably at that point the function should be changed to query
- * _NET_SUPPORTING_WM_CHECK only once every 10 seconds or something.
- */
-
- XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window,
- gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTING_WM_CHECK"),
- 0, G_MAXLONG, False, XA_WINDOW, &type, &format,
- &nitems, &bytes_after, (guchar **) & xwindow);
- if (type != XA_WINDOW)
+ if (supported_atoms->atoms == NULL)
return FALSE;
-
- gdk_error_trap_push ();
-
- /* Find out if this WM goes away, so we can reset everything. */
- XSelectInput (screen_x11->xdisplay, *xwindow, StructureNotifyMask);
-
- gdk_display_sync (screen_x11->display);
- if (gdk_error_trap_pop ())
+ i = 0;
+ while (i < supported_atoms->n_atoms)
{
- XFree (xwindow);
- return FALSE;
+ if (supported_atoms->atoms[i] == gdk_x11_atom_to_xatom_for_display (display, property))
+ return TRUE;
+
+ ++i;
}
- XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window,
- gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTED"),
- 0, G_MAXLONG, False, XA_ATOM, &type, &format,
- &supported_atoms->n_atoms, &bytes_after,
- (guchar **)&supported_atoms->atoms);
-
- if (type != XA_ATOM)
- return FALSE;
-
- screen_x11->wmspec_check_window = *xwindow;
- XFree (xwindow);
-
- /* since wmspec_check_window != None this isn't infinite. ;-) */
- return gdk_x11_screen_supports_net_wm_hint (screen, property);
+ return FALSE;
}
/**
gboolean
gdk_net_wm_supports (GdkAtom property)
{
- return gdk_x11_screen_supports_net_wm_hint (gdk_get_default_screen (), property);
+ return gdk_x11_screen_supports_net_wm_hint (gdk_screen_get_default (), property);
}
static struct
{ "Gtk/CanChangeAccels", "gtk-can-change-accels" },
{ "Gtk/ColorPalette", "gtk-color-palette" },
{ "Gtk/FontName", "gtk-font-name" },
+ { "Gtk/IconSizes", "gtk-icon-sizes" },
{ "Gtk/KeyThemeName", "gtk-key-theme-name" },
{ "Gtk/ToolbarStyle", "gtk-toolbar-style" },
{ "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
+ { "Gtk/IMPreeditStyle", "gtk-im-preedit-style" },
+ { "Gtk/IMStatusStyle", "gtk-im-status-style" },
{ "Net/CursorBlink", "gtk-cursor-blink" },
{ "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
{ "Net/ThemeName", "gtk-theme-name" }
{
GdkEvent new_event;
GdkScreen *screen = data;
+ GdkScreenX11 *screen_x11 = data;
int i;
+ if (screen_x11->xsettings_in_init)
+ return;
+
new_event.type = GDK_SETTING;
new_event.setting.window = gdk_screen_get_root_window (screen);
new_event.setting.send_event = FALSE;
for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
if (strcmp (settings_map[i].xsettings_name, name) == 0)
{
- new_event.setting.name = g_strdup (settings_map[i].gdk_name);
+ new_event.setting.name = (char *)settings_map[i].gdk_name;
break;
}
+
if (!new_event.setting.name)
return;
return TRUE;
}
-/**
- * gdk_setting_get:
- * @name: the name of the setting.
- * @value: location to store the value of the setting.
- *
- * Obtains a desktop-wide setting, such as the double-click time,
- * for the default screen. See gdk_screen_get_setting().
- *
- * Returns : %TRUE if the setting existed and a value was stored
- * in @value, %FALSE otherwise.
- **/
-gboolean
-gdk_setting_get (const gchar *name,
- GValue *value)
-{
- return gdk_screen_get_setting (gdk_get_default_screen (), name, value);
-}
-
/**
* gdk_screen_get_setting:
* @screen: the #GdkScreen where the setting is located
* FIXME needs a list of valid settings here, or a link to
* more information.
*
- * Returns : %TRUE if the setting existed and a value was stored
+ * Returns: %TRUE if the setting existed and a value was stored
* in @value, %FALSE otherwise.
+ *
+ * Since: 2.2
**/
gboolean
gdk_screen_get_setting (GdkScreen *screen,
static void
gdk_xsettings_watch_cb (Window window,
- Bool is_start,
- long mask,
- void *cb_data)
+ Bool is_start,
+ long mask,
+ void *cb_data)
{
GdkWindow *gdkwin;
GdkScreen *screen = cb_data;
gdkwin = gdk_window_lookup_for_display (gdk_screen_get_display (screen), window);
-
+
if (is_start)
- gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
+ {
+ if (!gdkwin)
+ gdkwin = gdk_window_foreign_new_for_display (gdk_screen_get_display (screen), window);
+ else
+ g_object_ref (gdkwin);
+
+ gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
+ }
else
- gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
+ {
+ g_assert (gdkwin);
+ gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
+ g_object_unref (gdkwin);
+ }
}