📄 gdkevents-x11.c
字号:
/* GDK - The GIMP Drawing Kit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */#include <config.h>#include "gdk.h"#include "gdkprivate-x11.h"#include "gdkinternals.h"#include "gdkx.h"#include "gdkscreen-x11.h"#include "gdkdisplay-x11.h"#include "gdkasync.h"#include "gdkkeysyms.h"#include "xsettings-client.h"#include <string.h>#include "gdkinputprivate.h"#include "gdkalias.h"#ifdef HAVE_XKB#include <X11/XKBlib.h>#endif#ifdef HAVE_XSYNC#include <X11/extensions/sync.h>#endif#ifdef HAVE_XFIXES#include <X11/extensions/Xfixes.h>#endif#include <X11/Xatom.h>typedef struct _GdkIOClosure GdkIOClosure;typedef struct _GdkDisplaySource GdkDisplaySource;typedef struct _GdkEventTypeX11 GdkEventTypeX11;struct _GdkIOClosure{ GdkInputFunction function; GdkInputCondition condition; GdkDestroyNotify notify; gpointer data;};struct _GdkDisplaySource{ GSource source; GdkDisplay *display; GPollFD event_poll_fd;};struct _GdkEventTypeX11{ gint base; gint n_events;};/* * Private function declarations */static gint gdk_event_apply_filters (XEvent *xevent, GdkEvent *event, GList *filters);static gboolean gdk_event_translate (GdkDisplay *display, GdkEvent *event, XEvent *xevent, gboolean return_exposes);static gboolean gdk_event_prepare (GSource *source, gint *timeout);static gboolean gdk_event_check (GSource *source);static gboolean gdk_event_dispatch (GSource *source, GSourceFunc callback, gpointer user_data);static GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev, GdkEvent *event, gpointer data);static GSource *gdk_display_source_new (GdkDisplay *display);static gboolean gdk_check_xpending (GdkDisplay *display);static void gdk_xsettings_watch_cb (Window window, Bool is_start, long mask, void *cb_data);static void gdk_xsettings_notify_cb (const char *name, XSettingsAction action, XSettingsSetting *setting, void *data);/* Private variable declarations */static GList *display_sources;static GSourceFuncs event_funcs = { gdk_event_prepare, gdk_event_check, gdk_event_dispatch, NULL};static GSource *gdk_display_source_new (GdkDisplay *display){ GSource *source = g_source_new (&event_funcs, sizeof (GdkDisplaySource)); GdkDisplaySource *display_source = (GdkDisplaySource *)source; display_source->display = display; return source;}static gbooleangdk_check_xpending (GdkDisplay *display){ return XPending (GDK_DISPLAY_XDISPLAY (display));}/********************************************* * Functions for maintaining the event queue * *********************************************/static voidrefcounted_grab_server (Display *xdisplay){ GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay); gdk_x11_display_grab (display);}static voidrefcounted_ungrab_server (Display *xdisplay){ GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay); gdk_x11_display_ungrab (display);}void_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); xsettings_client_set_grab_func (screen_x11->xsettings_client, refcounted_grab_server); xsettings_client_set_ungrab_func (screen_x11->xsettings_client, refcounted_ungrab_server); 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_events_init (GdkDisplay *display){ GSource *source; GdkDisplaySource *display_source; GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display); int connection_number = ConnectionNumber (display_x11->xdisplay); GDK_NOTE (MISC, g_message ("connection number: %d", connection_number)); source = display_x11->event_source = gdk_display_source_new (display); display_source = (GdkDisplaySource*) source; g_source_set_priority (source, GDK_PRIORITY_EVENTS); display_source->event_poll_fd.fd = connection_number; display_source->event_poll_fd.events = G_IO_IN; g_source_add_poll (source, &display_source->event_poll_fd); g_source_set_can_recurse (source, TRUE); g_source_attach (source, NULL); display_sources = g_list_prepend (display_sources,display_source); gdk_display_add_client_message_filter (display, gdk_atom_intern ("WM_PROTOCOLS", FALSE), gdk_wm_protocols_filter, NULL);}/** * gdk_events_pending: * * Checks if any events are ready to be processed for any display. * * Return value: %TRUE if any events are pending. **/gbooleangdk_events_pending (void){ GList *tmp_list; for (tmp_list = display_sources; tmp_list; tmp_list = tmp_list->next) { GdkDisplaySource *tmp_source = tmp_list->data; GdkDisplay *display = tmp_source->display; if (_gdk_event_queue_find_first (display)) return TRUE; } for (tmp_list = display_sources; tmp_list; tmp_list = tmp_list->next) { GdkDisplaySource *tmp_source = tmp_list->data; GdkDisplay *display = tmp_source->display; if (gdk_check_xpending (display)) return TRUE; } return FALSE;}static Boolgraphics_expose_predicate (Display *display, XEvent *xevent, XPointer arg){ if (xevent->xany.window == GDK_DRAWABLE_XID ((GdkDrawable *)arg) && (xevent->xany.type == GraphicsExpose || xevent->xany.type == NoExpose)) return True; else return False;}/** * gdk_event_get_graphics_expose: * @window: the #GdkWindow to wait for the events for. * * Waits for a GraphicsExpose or NoExpose event from the X server. * This is used in the #GtkText and #GtkCList widgets in GTK+ to make sure any * GraphicsExpose events are handled before the widget is scrolled. * * Return value: a #GdkEventExpose if a GraphicsExpose was received, or %NULL if a * NoExpose event was received. **/GdkEvent*gdk_event_get_graphics_expose (GdkWindow *window){ XEvent xevent; GdkEvent *event; g_return_val_if_fail (window != NULL, NULL); XIfEvent (GDK_WINDOW_XDISPLAY (window), &xevent, graphics_expose_predicate, (XPointer) window); if (xevent.xany.type == GraphicsExpose) { event = gdk_event_new (GDK_NOTHING); if (gdk_event_translate (GDK_WINDOW_DISPLAY (window), event, &xevent, TRUE)) return event; else gdk_event_free (event); } return NULL; }static gintgdk_event_apply_filters (XEvent *xevent, GdkEvent *event, GList *filters){ GList *tmp_list; GdkFilterReturn result; tmp_list = filters; while (tmp_list) { GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data; tmp_list = tmp_list->next; result = filter->function (xevent, event, filter->data); if (result != GDK_FILTER_CONTINUE) return result; } return GDK_FILTER_CONTINUE;}/** * gdk_display_add_client_message_filter: * @display: a #GdkDisplay for which this message filter applies * @message_type: the type of ClientMessage events to receive. * This will be checked against the @message_type field * of the XClientMessage event struct. * @func: the function to call to process the event. * @data: user data to pass to @func. * * Adds a filter to be called when X ClientMessage events are received. * * Since: 2.2 **/ void gdk_display_add_client_message_filter (GdkDisplay *display, GdkAtom message_type, GdkFilterFunc func, gpointer data){ GdkClientFilter *filter; g_return_if_fail (GDK_IS_DISPLAY (display)); filter = g_new (GdkClientFilter, 1); filter->type = message_type; filter->function = func; filter->data = data; GDK_DISPLAY_X11(display)->client_filters = g_list_append (GDK_DISPLAY_X11 (display)->client_filters, filter);}/** * gdk_add_client_message_filter: * @message_type: the type of ClientMessage events to receive. This will be * checked against the <structfield>message_type</structfield> field of the * XClientMessage event struct. * @func: the function to call to process the event. * @data: user data to pass to @func. * * Adds a filter to the default display to be called when X ClientMessage events * are received. See gdk_display_add_client_message_filter(). **/void gdk_add_client_message_filter (GdkAtom message_type, GdkFilterFunc func, gpointer data){ gdk_display_add_client_message_filter (gdk_display_get_default (), message_type, func, data);}static voiddo_net_wm_state_changes (GdkWindow *window){ GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window); GdkWindowState old_state; if (GDK_WINDOW_DESTROYED (window) || gdk_window_get_window_type (window) != GDK_WINDOW_TOPLEVEL) return; old_state = gdk_window_get_state (window); /* For found_sticky to remain TRUE, we have to also be on desktop * 0xFFFFFFFF */ if (old_state & GDK_WINDOW_STATE_STICKY) { if (!(toplevel->have_sticky && toplevel->on_all_desktops)) gdk_synthesize_window_state (window, GDK_WINDOW_STATE_STICKY, 0); } else { if (toplevel->have_sticky && toplevel->on_all_desktops) gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_STICKY); } if (old_state & GDK_WINDOW_STATE_FULLSCREEN) { if (!toplevel->have_fullscreen) gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0); } else { if (toplevel->have_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 */ if (old_state & GDK_WINDOW_STATE_MAXIMIZED) { if (!(toplevel->have_maxvert && toplevel->have_maxhorz)) gdk_synthesize_window_state (window, GDK_WINDOW_STATE_MAXIMIZED, 0); } else { if (toplevel->have_maxvert && toplevel->have_maxhorz) gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_MAXIMIZED); }}static voidgdk_check_wm_desktop_changed (GdkWindow *window){ GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window); GdkDisplay *display = GDK_WINDOW_DISPLAY (window); Atom type; gint format; gulong nitems; gulong bytes_after; if (toplevel->have_sticky) { guchar *data; gulong *desktop; type = None; gdk_error_trap_push ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -