diff --git a/ChangeLog b/ChangeLog index a468f0cd7a..602d64da14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,60 @@ +Fri Jul 4 15:57:52 2003 Owen Taylor + + * gdk/x11/gdkevents-x11.c (gdk_wm_protocols_filter): + Use asynchronously _gdk_x11_set_input_focus_safe + to avoid having to trap errors and XSync(). + + * gdk/x11/gdkwindow-x11.c (gdk_window_focus): Use + _gdk_x11_set_input_focus_safe() here as well. + + * gdk/x11/gdkevents-x11.c (gdk_check_wm_state_changed): + Rework handling of property notifies on _NET_WM_STATE + so that we ignore _NET_WM_DESKTOP notifies unless we + really care. + + * gdk/x11/gdkimage-x11.c (gdk_image_check_xshm): Use + XShmQueryExtension() rather than XQueryExtension() to + avoid extra rountrip. + + * gdk/x11/gdkwindow-x11.c (_gdk_windowing_window_init): + Remove unused call to XGetWindowAttributes() + + * gdk/x11/gdkdisplay-x11.c (gdk_display_open): Remove + unused call to XGetKeyboardControl(). + + * gdk/x11/gdkdisplay-x11.c gdk/gdk.def (gdk_display_flush): + Add (#99571) + + * gdk/win32/gdkevents-win32.c gdk/linux-fb/gdkevents-fb.c + No-op implementations of gdk_display_flush(). + + * gdk/gdkwindow.c (gdk_window_process_all_updates): Use + gdk_display_flush() rather than gdk_flush() to avoid + XSync(). + + * gdk/x11/gdkwindow-x11.c (update_wm_hints) + gdk/x11/gdkwindow-x11.h: Centralize all handling of WM_HINTS here + so that we don't have to get the property back from the server. + + * gdk/x11/gdkwindow-x11.c (show_window_internal): Store + the serial of when we map a toplevel to allow optimizing + out notifies on _NET_WM_STATE/_NET_WM_DESKTOP. + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Don't + XTranslateCoordinates() for override-redirect windows. + +Fri Jul 4 15:59:27 2003 Owen Taylor + + * gdk/x11/gdkwindow-x11.c (gdk_window_set_group): Remove comment + about setting window group after the window is mapped from docs + - nothing the ICCCM forbids that. + + * gdk/x11/gdkcursor-x11.c (gdk_display_get_maximal_cursor_size): + Fix g_return_val_if_fail() in void return function. + + * configure.in: Fix misplaced comma that was resulting + in XShm always being disabled. + Fri Jul 4 19:55:49 2003 Soeren Sandmann * tests/stresstest-toolbar: remove this accidentally committed diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index a468f0cd7a..602d64da14 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,60 @@ +Fri Jul 4 15:57:52 2003 Owen Taylor + + * gdk/x11/gdkevents-x11.c (gdk_wm_protocols_filter): + Use asynchronously _gdk_x11_set_input_focus_safe + to avoid having to trap errors and XSync(). + + * gdk/x11/gdkwindow-x11.c (gdk_window_focus): Use + _gdk_x11_set_input_focus_safe() here as well. + + * gdk/x11/gdkevents-x11.c (gdk_check_wm_state_changed): + Rework handling of property notifies on _NET_WM_STATE + so that we ignore _NET_WM_DESKTOP notifies unless we + really care. + + * gdk/x11/gdkimage-x11.c (gdk_image_check_xshm): Use + XShmQueryExtension() rather than XQueryExtension() to + avoid extra rountrip. + + * gdk/x11/gdkwindow-x11.c (_gdk_windowing_window_init): + Remove unused call to XGetWindowAttributes() + + * gdk/x11/gdkdisplay-x11.c (gdk_display_open): Remove + unused call to XGetKeyboardControl(). + + * gdk/x11/gdkdisplay-x11.c gdk/gdk.def (gdk_display_flush): + Add (#99571) + + * gdk/win32/gdkevents-win32.c gdk/linux-fb/gdkevents-fb.c + No-op implementations of gdk_display_flush(). + + * gdk/gdkwindow.c (gdk_window_process_all_updates): Use + gdk_display_flush() rather than gdk_flush() to avoid + XSync(). + + * gdk/x11/gdkwindow-x11.c (update_wm_hints) + gdk/x11/gdkwindow-x11.h: Centralize all handling of WM_HINTS here + so that we don't have to get the property back from the server. + + * gdk/x11/gdkwindow-x11.c (show_window_internal): Store + the serial of when we map a toplevel to allow optimizing + out notifies on _NET_WM_STATE/_NET_WM_DESKTOP. + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Don't + XTranslateCoordinates() for override-redirect windows. + +Fri Jul 4 15:59:27 2003 Owen Taylor + + * gdk/x11/gdkwindow-x11.c (gdk_window_set_group): Remove comment + about setting window group after the window is mapped from docs + - nothing the ICCCM forbids that. + + * gdk/x11/gdkcursor-x11.c (gdk_display_get_maximal_cursor_size): + Fix g_return_val_if_fail() in void return function. + + * configure.in: Fix misplaced comma that was resulting + in XShm always being disabled. + Fri Jul 4 19:55:49 2003 Soeren Sandmann * tests/stresstest-toolbar: remove this accidentally committed diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index a468f0cd7a..602d64da14 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,60 @@ +Fri Jul 4 15:57:52 2003 Owen Taylor + + * gdk/x11/gdkevents-x11.c (gdk_wm_protocols_filter): + Use asynchronously _gdk_x11_set_input_focus_safe + to avoid having to trap errors and XSync(). + + * gdk/x11/gdkwindow-x11.c (gdk_window_focus): Use + _gdk_x11_set_input_focus_safe() here as well. + + * gdk/x11/gdkevents-x11.c (gdk_check_wm_state_changed): + Rework handling of property notifies on _NET_WM_STATE + so that we ignore _NET_WM_DESKTOP notifies unless we + really care. + + * gdk/x11/gdkimage-x11.c (gdk_image_check_xshm): Use + XShmQueryExtension() rather than XQueryExtension() to + avoid extra rountrip. + + * gdk/x11/gdkwindow-x11.c (_gdk_windowing_window_init): + Remove unused call to XGetWindowAttributes() + + * gdk/x11/gdkdisplay-x11.c (gdk_display_open): Remove + unused call to XGetKeyboardControl(). + + * gdk/x11/gdkdisplay-x11.c gdk/gdk.def (gdk_display_flush): + Add (#99571) + + * gdk/win32/gdkevents-win32.c gdk/linux-fb/gdkevents-fb.c + No-op implementations of gdk_display_flush(). + + * gdk/gdkwindow.c (gdk_window_process_all_updates): Use + gdk_display_flush() rather than gdk_flush() to avoid + XSync(). + + * gdk/x11/gdkwindow-x11.c (update_wm_hints) + gdk/x11/gdkwindow-x11.h: Centralize all handling of WM_HINTS here + so that we don't have to get the property back from the server. + + * gdk/x11/gdkwindow-x11.c (show_window_internal): Store + the serial of when we map a toplevel to allow optimizing + out notifies on _NET_WM_STATE/_NET_WM_DESKTOP. + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Don't + XTranslateCoordinates() for override-redirect windows. + +Fri Jul 4 15:59:27 2003 Owen Taylor + + * gdk/x11/gdkwindow-x11.c (gdk_window_set_group): Remove comment + about setting window group after the window is mapped from docs + - nothing the ICCCM forbids that. + + * gdk/x11/gdkcursor-x11.c (gdk_display_get_maximal_cursor_size): + Fix g_return_val_if_fail() in void return function. + + * configure.in: Fix misplaced comma that was resulting + in XShm always being disabled. + Fri Jul 4 19:55:49 2003 Soeren Sandmann * tests/stresstest-toolbar: remove this accidentally committed diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index a468f0cd7a..602d64da14 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,60 @@ +Fri Jul 4 15:57:52 2003 Owen Taylor + + * gdk/x11/gdkevents-x11.c (gdk_wm_protocols_filter): + Use asynchronously _gdk_x11_set_input_focus_safe + to avoid having to trap errors and XSync(). + + * gdk/x11/gdkwindow-x11.c (gdk_window_focus): Use + _gdk_x11_set_input_focus_safe() here as well. + + * gdk/x11/gdkevents-x11.c (gdk_check_wm_state_changed): + Rework handling of property notifies on _NET_WM_STATE + so that we ignore _NET_WM_DESKTOP notifies unless we + really care. + + * gdk/x11/gdkimage-x11.c (gdk_image_check_xshm): Use + XShmQueryExtension() rather than XQueryExtension() to + avoid extra rountrip. + + * gdk/x11/gdkwindow-x11.c (_gdk_windowing_window_init): + Remove unused call to XGetWindowAttributes() + + * gdk/x11/gdkdisplay-x11.c (gdk_display_open): Remove + unused call to XGetKeyboardControl(). + + * gdk/x11/gdkdisplay-x11.c gdk/gdk.def (gdk_display_flush): + Add (#99571) + + * gdk/win32/gdkevents-win32.c gdk/linux-fb/gdkevents-fb.c + No-op implementations of gdk_display_flush(). + + * gdk/gdkwindow.c (gdk_window_process_all_updates): Use + gdk_display_flush() rather than gdk_flush() to avoid + XSync(). + + * gdk/x11/gdkwindow-x11.c (update_wm_hints) + gdk/x11/gdkwindow-x11.h: Centralize all handling of WM_HINTS here + so that we don't have to get the property back from the server. + + * gdk/x11/gdkwindow-x11.c (show_window_internal): Store + the serial of when we map a toplevel to allow optimizing + out notifies on _NET_WM_STATE/_NET_WM_DESKTOP. + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Don't + XTranslateCoordinates() for override-redirect windows. + +Fri Jul 4 15:59:27 2003 Owen Taylor + + * gdk/x11/gdkwindow-x11.c (gdk_window_set_group): Remove comment + about setting window group after the window is mapped from docs + - nothing the ICCCM forbids that. + + * gdk/x11/gdkcursor-x11.c (gdk_display_get_maximal_cursor_size): + Fix g_return_val_if_fail() in void return function. + + * configure.in: Fix misplaced comma that was resulting + in XShm always being disabled. + Fri Jul 4 19:55:49 2003 Soeren Sandmann * tests/stresstest-toolbar: remove this accidentally committed diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index a468f0cd7a..602d64da14 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,60 @@ +Fri Jul 4 15:57:52 2003 Owen Taylor + + * gdk/x11/gdkevents-x11.c (gdk_wm_protocols_filter): + Use asynchronously _gdk_x11_set_input_focus_safe + to avoid having to trap errors and XSync(). + + * gdk/x11/gdkwindow-x11.c (gdk_window_focus): Use + _gdk_x11_set_input_focus_safe() here as well. + + * gdk/x11/gdkevents-x11.c (gdk_check_wm_state_changed): + Rework handling of property notifies on _NET_WM_STATE + so that we ignore _NET_WM_DESKTOP notifies unless we + really care. + + * gdk/x11/gdkimage-x11.c (gdk_image_check_xshm): Use + XShmQueryExtension() rather than XQueryExtension() to + avoid extra rountrip. + + * gdk/x11/gdkwindow-x11.c (_gdk_windowing_window_init): + Remove unused call to XGetWindowAttributes() + + * gdk/x11/gdkdisplay-x11.c (gdk_display_open): Remove + unused call to XGetKeyboardControl(). + + * gdk/x11/gdkdisplay-x11.c gdk/gdk.def (gdk_display_flush): + Add (#99571) + + * gdk/win32/gdkevents-win32.c gdk/linux-fb/gdkevents-fb.c + No-op implementations of gdk_display_flush(). + + * gdk/gdkwindow.c (gdk_window_process_all_updates): Use + gdk_display_flush() rather than gdk_flush() to avoid + XSync(). + + * gdk/x11/gdkwindow-x11.c (update_wm_hints) + gdk/x11/gdkwindow-x11.h: Centralize all handling of WM_HINTS here + so that we don't have to get the property back from the server. + + * gdk/x11/gdkwindow-x11.c (show_window_internal): Store + the serial of when we map a toplevel to allow optimizing + out notifies on _NET_WM_STATE/_NET_WM_DESKTOP. + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Don't + XTranslateCoordinates() for override-redirect windows. + +Fri Jul 4 15:59:27 2003 Owen Taylor + + * gdk/x11/gdkwindow-x11.c (gdk_window_set_group): Remove comment + about setting window group after the window is mapped from docs + - nothing the ICCCM forbids that. + + * gdk/x11/gdkcursor-x11.c (gdk_display_get_maximal_cursor_size): + Fix g_return_val_if_fail() in void return function. + + * configure.in: Fix misplaced comma that was resulting + in XShm always being disabled. + Fri Jul 4 19:55:49 2003 Soeren Sandmann * tests/stresstest-toolbar: remove this accidentally committed diff --git a/configure.in b/configure.in index 76b7dffc9c..c37defee6b 100644 --- a/configure.in +++ b/configure.in @@ -161,8 +161,8 @@ AC_ARG_ENABLE(debug, enable_debug=debug_default) AC_ARG_ENABLE(shm, [AC_HELP_STRING([--enable-shm], - [support shared memory if available [default=yes]])], - [echo $enable_shm, enable_shm="yes"]) + [support shared memory if available [default=yes]])],, + [enable_shm="yes"]) AC_ARG_ENABLE(ansi, [AC_HELP_STRING([--enable-ansi], [turn on strict ansi [default=no]])],, diff --git a/gdk/gdk.def b/gdk/gdk.def index 27e2a20557..01ea9db72d 100644 --- a/gdk/gdk.def +++ b/gdk/gdk.def @@ -60,6 +60,7 @@ EXPORTS gdk_display_add_client_message_filter gdk_display_beep gdk_display_close + gdk_display_flush gdk_display_get_core_pointer gdk_display_get_default gdk_display_get_default_screen diff --git a/gdk/gdkdisplay.h b/gdk/gdkdisplay.h index 8314240143..db6df0cd4f 100644 --- a/gdk/gdkdisplay.h +++ b/gdk/gdkdisplay.h @@ -113,6 +113,8 @@ void gdk_display_keyboard_ungrab (GdkDisplay *display, gboolean gdk_display_pointer_is_grabbed (GdkDisplay *display); void gdk_display_beep (GdkDisplay *display); void gdk_display_sync (GdkDisplay *display); +void gdk_display_flush (GdkDisplay *display); + void gdk_display_close (GdkDisplay *display); GList * gdk_display_list_devices (GdkDisplay *display); diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 21310ceb2b..00c708c7bb 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -2144,6 +2144,18 @@ gdk_window_process_updates_internal (GdkWindow *window) } } +static void +flush_all_displays (void) +{ + GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ()); + GSList *tmp_list; + + for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next) + gdk_display_flush (tmp_list->data); + + g_slist_free (displays); +} + /** * gdk_window_process_all_updates: * @@ -2174,7 +2186,7 @@ gdk_window_process_all_updates (void) g_slist_free (old_update_windows); - gdk_flush(); + flush_all_displays (); } static gboolean diff --git a/gdk/linux-fb/gdkevents-fb.c b/gdk/linux-fb/gdkevents-fb.c index b61377e4db..9001da48ed 100644 --- a/gdk/linux-fb/gdkevents-fb.c +++ b/gdk/linux-fb/gdkevents-fb.c @@ -225,3 +225,8 @@ void gdk_display_sync (GdkDisplay *display) { } + +void +gdk_display_flush (GdkDisplay * display) +{ +} diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c index 841835bc79..4838d0891b 100644 --- a/gdk/win32/gdkevents-win32.c +++ b/gdk/win32/gdkevents-win32.c @@ -3516,3 +3516,11 @@ gdk_display_sync (GdkDisplay * display) DispatchMessage (&msg); } } + +void +gdk_display_flush (GdkDisplay * display) +{ + g_return_if_fail (display == gdk_display_get_default ()); + + /* Nothing */ +} diff --git a/gdk/x11/Makefile.am b/gdk/x11/Makefile.am index 51ca918265..3fb2f2b1d4 100644 --- a/gdk/x11/Makefile.am +++ b/gdk/x11/Makefile.am @@ -20,6 +20,8 @@ noinst_LTLIBRARIES = libgdk-x11.la libgdk_x11_la_SOURCES = \ MwmUtil.h \ + gdkasync.c \ + gdkasync.h \ gdkcolor-x11.c \ gdkcursor-x11.c \ gdkdisplay-x11.c \ diff --git a/gdk/x11/gdkasync.c b/gdk/x11/gdkasync.c new file mode 100644 index 0000000000..5f2672bda4 --- /dev/null +++ b/gdk/x11/gdkasync.c @@ -0,0 +1,156 @@ +/* GTK - The GIMP Toolkit + * gdkasync.c: Utility functions using the Xlib asynchronous interfaces + * Copyright (C) 2003, Red Hat, Inc. + * + * 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. + */ +/* Portions of code in this file are based on code from Xlib + */ +/* +Copyright 1986, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +#include +#include "gdkasync.h" +#include "gdkx.h" + +typedef struct _SetInputFocusState SetInputFocusState; + +struct _SetInputFocusState +{ + Display *dpy; + Window window; + _XAsyncHandler async; + gulong set_input_focus_req; + gulong get_input_focus_req; + gboolean have_error; + GdkSendXEventCallback callback; + gpointer data; +}; + +static Bool +set_input_focus_handler (Display *dpy, + xReply *rep, + char *buf, + int len, + XPointer data) +{ + SetInputFocusState *state = (SetInputFocusState *)data; + + if (dpy->last_request_read == state->set_input_focus_req) + { + if (rep->generic.type == X_Error && + rep->error.errorCode == BadMatch) + { + /* Consume BadMatch errors, since we have no control + * over them. + */ + return True; + } + } + + if (dpy->last_request_read == state->get_input_focus_req) + { + xGetInputFocusReply replbuf; + xGetInputFocusReply *repl; + + if (rep->generic.type != X_Error) + { + /* Actually does nothing, since there are no additional bytes + * to read, but maintain good form. + */ + repl = (xGetInputFocusReply *) + _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len, + (sizeof(xGetInputFocusReply) - sizeof(xReply)) >> 2, + True); + } + + DeqAsyncHandler(state->dpy, &state->async); + + g_free (state); + + return (rep->generic.type != X_Error); + } + + return False; +} + +void +_gdk_x11_set_input_focus_safe (GdkDisplay *display, + Window window, + int revert_to, + Time time) +{ + Display *dpy; + SetInputFocusState *state; + + dpy = GDK_DISPLAY_XDISPLAY (display); + + state = g_new (SetInputFocusState, 1); + + state->dpy = dpy; + state->window = window; + + LockDisplay(dpy); + + state->async.next = dpy->async_handlers; + state->async.handler = set_input_focus_handler; + state->async.data = (XPointer) state; + dpy->async_handlers = &state->async; + + { + xSetInputFocusReq *req; + + GetReq(SetInputFocus, req); + req->focus = window; + req->revertTo = revert_to; + req->time = time; + state->set_input_focus_req = dpy->request; + } + + /* + * XSync (dpy, 0) + */ + { + xReq *req; + + GetEmptyReq(GetInputFocus, req); + state->get_input_focus_req = dpy->request; + } + + UnlockDisplay(dpy); + SyncHandle(); +} diff --git a/gdk/x11/gdkasync.h b/gdk/x11/gdkasync.h new file mode 100644 index 0000000000..2da6040304 --- /dev/null +++ b/gdk/x11/gdkasync.h @@ -0,0 +1,36 @@ +/* GTK - The GIMP Toolkit + * gdkasync.h: Utility functions using the Xlib asynchronous interfaces + * Copyright (C) 2003, Red Hat, Inc. + * + * 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. + */ + +#ifndef __GDK_ASYNC_H__ +#define __GDK_ASYNC_H__ + +#include +#include "gdk.h" + +G_BEGIN_DECLS + +void _gdk_x11_set_input_focus_safe (GdkDisplay *display, + Window window, + int revert_to, + Time time); + +G_END_DECLS + +#endif /* __GDK_ASYNC_H__ */ diff --git a/gdk/x11/gdkcursor-x11.c b/gdk/x11/gdkcursor-x11.c index 80f4bf9f84..d872709191 100644 --- a/gdk/x11/gdkcursor-x11.c +++ b/gdk/x11/gdkcursor-x11.c @@ -587,7 +587,7 @@ gdk_display_get_maximal_cursor_size (GdkDisplay *display, GdkScreen *screen; GdkWindow *window; - g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE); + g_return_if_fail (GDK_IS_DISPLAY (display)); screen = gdk_display_get_default_screen (display); window = gdk_screen_get_root_window (screen); diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index 66ec5c36e7..969ccb71ed 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -57,6 +57,32 @@ static void gdk_internal_connection_watch (Display *display, static gpointer parent_class = NULL; +/* Note that we never *directly* use WM_LOCALE_NAME, WM_PROTOCOLS, + * but including them here has the side-effect of getting them + * into the internal Xlib cache + */ +static const char *const precache_atoms[] = { + "UTF8_STRING", + "WM_CLIENT_LEADER", + "WM_DELETE_WINDOW", + "WM_LOCALE_NAME", + "WM_PROTOCOLS", + "WM_TAKE_FOCUS", + "_NET_WM_DESKTOP", + "_NET_WM_ICON", + "_NET_WM_ICON_NAME", + "_NET_WM_NAME", + "_NET_WM_PID", + "_NET_WM_PING", + "_NET_WM_STATE", + "_NET_WM_STATE_STICKY", + "_NET_WM_STATE_MAXIMIZED_VERT", + "_NET_WM_STATE_MAXIMIZED_HORZ", + "_NET_WM_STATE_FULLSCREEN", + "_NET_WM_WINDOW_TYPE", + "_NET_WM_WINDOW_TYPE_NORMAL", +}; + GType _gdk_display_x11_get_type (void) { @@ -117,7 +143,6 @@ gdk_display_open (const gchar *display_name) const char *sm_client_id; XClassHint *class_hint; - XKeyboardState keyboard_state; gulong pid; gint i; @@ -162,6 +187,8 @@ gdk_display_open (const gchar *display_name) if (_gdk_synchronize) XSynchronize (display_x11->xdisplay, True); + _gdk_x11_precache_atoms (display, precache_atoms, G_N_ELEMENTS (precache_atoms)); + class_hint = XAllocClassHint(); class_hint->res_name = g_get_prgname (); @@ -183,8 +210,6 @@ gdk_display_open (const gchar *display_name) gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID"), XA_CARDINAL, 32, PropModeReplace, (guchar *) & pid, 1); - XGetKeyboardControl (display_x11->xdisplay, &keyboard_state); - #ifdef HAVE_XKB { gint xkb_major = XkbMajorVersion; @@ -509,6 +534,31 @@ gdk_display_sync (GdkDisplay * display) XSync (GDK_DISPLAY_XDISPLAY (display), False); } +/** + * gdk_display_flush: + * @display: a #GdkDisplay + * + * Flushes any requests queued for the windowing system; this happens automatically + * when the main loop blocks waiting for new events, but if your application + * is drawing without returning control to the main loop, you may need + * to call this function explicitely. A common case where this function + * needs to be called is when an application is executing drawing commands + * from a thread other than the thread where the main loop is running. + * + * This is most useful for X11. On windowing systems where requests are + * handled synchronously, this function will do nothing. + * + * Since: 2.4 + */ +void +gdk_display_flush (GdkDisplay *display) +{ + g_return_if_fail (GDK_IS_DISPLAY (display)); + + if (!display->closed) + XFlush (GDK_DISPLAY_XDISPLAY (display)); +} + /** * gdk_x11_display_grab: * @display: a #GdkDisplay diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index 7bb9d63d7c..4e3db600cb 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -30,6 +30,7 @@ #include "gdkx.h" #include "gdkscreen-x11.h" #include "gdkdisplay-x11.h" +#include "gdkasync.h" #include "gdkkeysyms.h" @@ -357,28 +358,122 @@ gdk_add_client_message_filter (GdkAtom message_type, } static void -gdk_check_wm_state_changed (GdkWindow *window) +do_net_wm_state_changes (GdkWindow *window) { + GdkWindowObject *window_private = (GdkWindowObject *)window; + GdkWindowImplX11 *window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl); + 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 (!(window_impl->have_sticky && window_impl->on_all_desktops)) + gdk_synthesize_window_state (window, + GDK_WINDOW_STATE_STICKY, + 0); + } + else + { + if (window_impl->have_sticky && window_impl->on_all_desktops) + gdk_synthesize_window_state (window, + 0, + GDK_WINDOW_STATE_STICKY); + } + + if (old_state & GDK_WINDOW_STATE_FULLSCREEN) + { + if (!window_impl->have_fullscreen) + gdk_synthesize_window_state (window, + GDK_WINDOW_STATE_FULLSCREEN, + 0); + } + else + { + if (window_impl->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 (!(window_impl->have_maxvert && window_impl->have_maxhorz)) + gdk_synthesize_window_state (window, + GDK_WINDOW_STATE_MAXIMIZED, + 0); + } + else + { + if (window_impl->have_maxvert && window_impl->have_maxhorz) + gdk_synthesize_window_state (window, + 0, + GDK_WINDOW_STATE_MAXIMIZED); + } +} + +static void +gdk_check_wm_desktop_changed (GdkWindow *window) +{ + GdkWindowObject *window_private = (GdkWindowObject *)window; + GdkWindowImplX11 *window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl); + GdkDisplay *display = GDK_WINDOW_DISPLAY (window); + + Atom type; + gint format; + gulong nitems; + gulong bytes_after; + + if (window_impl->have_sticky) + { + gulong *desktop; + + XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), + GDK_WINDOW_XID (window), + gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"), + 0, G_MAXLONG, False, XA_CARDINAL, &type, + &format, &nitems, + &bytes_after, (guchar **)&desktop); + + if (type != None) + { + window_impl->on_all_desktops = (*desktop == 0xFFFFFFFF); + XFree (desktop); + } + else + window_impl->on_all_desktops = FALSE; + + do_net_wm_state_changes (window); + } +} + +static void +gdk_check_wm_state_changed (GdkWindow *window) +{ + GdkWindowObject *window_private = (GdkWindowObject *)window; + GdkWindowImplX11 *window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl); + GdkDisplay *display = GDK_WINDOW_DISPLAY (window); + Atom type; gint format; gulong nitems; gulong bytes_after; Atom *atoms = NULL; gulong i; - gboolean found_sticky, found_maxvert, found_maxhorz, found_fullscreen; - GdkWindowState old_state; - GdkDisplay *display = GDK_WINDOW_DISPLAY (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), + + gboolean had_sticky = window_impl->have_sticky; + + XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"), 0, G_MAXLONG, False, XA_ATOM, &type, &format, &nitems, &bytes_after, (guchar **)&atoms); @@ -394,13 +489,13 @@ gdk_check_wm_state_changed (GdkWindow *window) while (i < nitems) { if (atoms[i] == sticky_atom) - found_sticky = TRUE; + window_impl->have_sticky = TRUE; else if (atoms[i] == maxvert_atom) - found_maxvert = TRUE; + window_impl->have_maxvert = TRUE; else if (atoms[i] == maxhorz_atom) - found_maxhorz = TRUE; + window_impl->have_maxhorz = TRUE; else if (atoms[i] == fullscreen_atom) - found_fullscreen = TRUE; + window_impl->have_fullscreen = TRUE; ++i; } @@ -408,79 +503,13 @@ gdk_check_wm_state_changed (GdkWindow *window) XFree (atoms); } - /* For found_sticky to remain TRUE, we have to also be on desktop - * 0xFFFFFFFF + /* When have_sticky is turned on, we have to check the DESKTOP property + * as well. */ - - if (found_sticky) - { - gulong *desktop; - - XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - gdk_x11_get_xatom_by_name_for_display - (display, "_NET_WM_DESKTOP"), - 0, G_MAXLONG, False, XA_CARDINAL, &type, - &format, &nitems, - &bytes_after, (guchar **)&desktop); - - if (type != None) - { - if (*desktop != 0xFFFFFFFF) - found_sticky = FALSE; - XFree (desktop); - } - } - - old_state = gdk_window_get_state (window); - - if (old_state & GDK_WINDOW_STATE_STICKY) - { - if (!found_sticky) - gdk_synthesize_window_state (window, - GDK_WINDOW_STATE_STICKY, - 0); - } + if (window_impl->have_sticky && !had_sticky) + gdk_check_wm_desktop_changed (window); else - { - if (found_sticky) - gdk_synthesize_window_state (window, - 0, - 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 - */ - if (old_state & GDK_WINDOW_STATE_MAXIMIZED) - { - if (!(found_maxvert && found_maxhorz)) - gdk_synthesize_window_state (window, - GDK_WINDOW_STATE_MAXIMIZED, - 0); - } - else - { - if (found_maxvert && found_maxhorz) - gdk_synthesize_window_state (window, - 0, - GDK_WINDOW_STATE_MAXIMIZED); - } + do_net_wm_state_changes (window); } #define HAS_FOCUS(window_impl) \ @@ -1590,7 +1619,8 @@ gdk_event_translate (GdkDisplay *display, event->configure.width = xevent->xconfigure.width; event->configure.height = xevent->xconfigure.height; - if (!xevent->xconfigure.send_event && + if (!xevent->xconfigure.send_event && + !xevent->xconfigure.override_redirect && !GDK_WINDOW_DESTROYED (window)) { gint tx = 0; @@ -1605,14 +1635,10 @@ gdk_event_translate (GdkDisplay *display, &tx, &ty, &child_window)) { - if (!gdk_error_trap_pop ()) - { - event->configure.x = tx; - event->configure.y = ty; - } + event->configure.x = tx; + event->configure.y = ty; } - else - gdk_error_trap_pop (); + gdk_error_trap_pop (); } else { @@ -1647,13 +1673,18 @@ gdk_event_translate (GdkDisplay *display, return_val = FALSE; break; } - - 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 (window); - } + + /* We compare with the serial of the last time we mapped the + * window to avoid refetching properties that we set ourselves + */ + if (xevent->xproperty.serial >= GDK_WINDOW_IMPL_X11 (window_private->impl)->map_serial) + { + if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE")) + gdk_check_wm_state_changed (window); + + if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP")) + gdk_check_wm_desktop_changed (window); + } if (window_private->event_mask & GDK_PROPERTY_CHANGE_MASK) { @@ -1876,18 +1907,14 @@ gdk_wm_protocols_filter (GdkXEvent *xev, else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS")) { GdkWindow *win = event->any.window; - Window focus_win = GDK_WINDOW_IMPL_X11(((GdkWindowObject *)win)->impl)->focus_window; + GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)win)->impl); - /* There is no way of knowing reliably whether we are viewable so we need - * to trap errors so we don't cause a BadMatch. + /* There is no way of knowing reliably whether we are viewable; + * _gdk_x11_set_input_focus_safe() traps errors asynchronously. */ - gdk_error_trap_push (); - XSetInputFocus (GDK_WINDOW_XDISPLAY (win), - focus_win, - RevertToParent, - xevent->xclient.data.l[1]); - XSync (GDK_WINDOW_XDISPLAY (win), False); - gdk_error_trap_pop (); + _gdk_x11_set_input_focus_safe (display, impl->focus_window, + RevertToParent, + xevent->xclient.data.l[1]); } else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING") && !_gdk_x11_display_is_root_window (display, @@ -2190,8 +2217,8 @@ timestamp_predicate (Display *display, if (xevent->type == PropertyNotify && xevent->xproperty.window == xwindow && - xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display - (gdk_display, "GDK_TIMESTAMP_PROP")) + xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display, + "GDK_TIMESTAMP_PROP")) return True; return False; diff --git a/gdk/x11/gdkimage-x11.c b/gdk/x11/gdkimage-x11.c index 4db96354bf..06bf212bf9 100644 --- a/gdk/x11/gdkimage-x11.c +++ b/gdk/x11/gdkimage-x11.c @@ -205,16 +205,12 @@ static int gdk_image_check_xshm(Display *display) { #ifdef USE_SHM - int major, minor, ignore; + int major, minor; Bool pixmaps; - if (XQueryExtension(display, "MIT-SHM", &ignore, &ignore, &ignore)) - { - if (XShmQueryVersion(display, &major, &minor, &pixmaps )==True) - { - return (pixmaps==True) ? 2 : 1; - } - } + if (XShmQueryExtension (display) && + XShmQueryVersion (display, &major, &minor, &pixmaps)) + return pixmaps ? 2 : 1; #endif /* USE_SHM */ return 0; } diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index f6f62a3bab..3543d86cc6 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -167,6 +167,10 @@ void _gdk_xgrab_check_destroy (GdkWindow *window); gboolean _gdk_x11_display_is_root_window (GdkDisplay *display, Window xroot_window); +void _gdk_x11_precache_atoms (GdkDisplay *display, + const gchar * const *atom_names, + gint n_atoms); + void _gdk_x11_events_init_screen (GdkScreen *screen); void _gdk_x11_events_uninit_screen (GdkScreen *screen); diff --git a/gdk/x11/gdkproperty-x11.c b/gdk/x11/gdkproperty-x11.c index 139c5b52c8..bedea12d12 100644 --- a/gdk/x11/gdkproperty-x11.c +++ b/gdk/x11/gdkproperty-x11.c @@ -142,6 +142,23 @@ insert_atom_pair (GdkDisplay *display, GUINT_TO_POINTER (xatom), GDK_ATOM_TO_POINTER (virtual_atom)); } + +static Atom +lookup_cached_xatom (GdkDisplay *display, + GdkAtom atom) +{ + GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display); + + if (ATOM_TO_INDEX (atom) < G_N_ELEMENTS (XAtomsStrings) - N_CUSTOM_PREDEFINED) + return ATOM_TO_INDEX (atom); + + if (display_x11->atom_from_virtual) + return GPOINTER_TO_UINT (g_hash_table_lookup (display_x11->atom_from_virtual, + GDK_ATOM_TO_POINTER (atom))); + + return None; +} + /** * gdk_x11_atom_to_xatom_for_display: * @display: A #GdkDisplay @@ -158,7 +175,6 @@ Atom gdk_x11_atom_to_xatom_for_display (GdkDisplay *display, GdkAtom atom) { - GdkDisplayX11 *display_x11; Atom xatom = None; g_return_val_if_fail (GDK_IS_DISPLAY (display), None); @@ -166,14 +182,8 @@ gdk_x11_atom_to_xatom_for_display (GdkDisplay *display, if (display->closed) return None; - display_x11 = GDK_DISPLAY_X11 (display); + xatom = lookup_cached_xatom (display, atom); - if (ATOM_TO_INDEX (atom) < G_N_ELEMENTS (XAtomsStrings) - N_CUSTOM_PREDEFINED) - return ATOM_TO_INDEX (atom); - - if (display_x11->atom_from_virtual) - xatom = GPOINTER_TO_UINT (g_hash_table_lookup (display_x11->atom_from_virtual, - GDK_ATOM_TO_POINTER (atom))); if (!xatom) { char *name; @@ -189,6 +199,45 @@ gdk_x11_atom_to_xatom_for_display (GdkDisplay *display, return xatom; } +void +_gdk_x11_precache_atoms (GdkDisplay *display, + const gchar * const *atom_names, + gint n_atoms) +{ + Atom *xatoms; + GdkAtom *atoms; + const gchar **xatom_names; + gint n_xatoms; + gint i; + + xatoms = g_new (Atom, n_atoms); + xatom_names = g_new (const gchar *, n_atoms); + atoms = g_new (GdkAtom, n_atoms); + + n_xatoms = 0; + for (i = 0; i < n_atoms; i++) + { + GdkAtom atom = gdk_atom_intern (atom_names[i], FALSE); + if (lookup_cached_xatom (display, atom) == None) + { + atoms[n_xatoms] = atom; + xatom_names[n_xatoms] = atom_names[i]; + n_xatoms++; + } + } + + if (n_xatoms) + XInternAtoms (GDK_DISPLAY_XDISPLAY (display), + (char **)xatom_names, n_xatoms, False, xatoms); + + for (i = 0; i < n_xatoms; i++) + insert_atom_pair (display, atoms[i], xatoms[i]); + + g_free (xatoms); + g_free (atoms); + g_free (atom_names); +} + /** * gdk_x11_atom_to_xatom: * @atom: A #GdkAtom diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 13799250aa..ffd8d583e5 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -33,6 +33,7 @@ #include "config.h" #include "gdkwindow.h" +#include "gdkasync.h" #include "gdkinputprivate.h" #include "gdkdisplay-x11.h" #include "gdkprivate-x11.h" @@ -283,12 +284,6 @@ _gdk_windowing_window_init (GdkScreen * screen) GdkWindowImplX11 *impl; GdkDrawableImplX11 *draw_impl; GdkScreenX11 *screen_x11; - XWindowAttributes xattributes; - unsigned int width; - unsigned int height; - unsigned int border_width; - unsigned int depth; - int x, y; screen_x11 = GDK_SCREEN_X11 (screen); @@ -297,10 +292,6 @@ _gdk_windowing_window_init (GdkScreen * screen) gdk_screen_set_default_colormap (screen, gdk_screen_get_system_colormap (screen)); - XGetGeometry (screen_x11->xdisplay, screen_x11->xroot_window, - &screen_x11->xroot_window, &x, &y, &width, &height, &border_width, &depth); - XGetWindowAttributes (screen_x11->xdisplay, screen_x11->xroot_window, &xattributes); - screen_x11->root_window = g_object_new (GDK_TYPE_WINDOW, NULL); private = (GdkWindowObject *)screen_x11->root_window; impl = GDK_WINDOW_IMPL_X11 (private->impl); @@ -313,10 +304,10 @@ _gdk_windowing_window_init (GdkScreen * screen) g_object_ref (draw_impl->colormap); private->window_type = GDK_WINDOW_ROOT; - private->depth = depth; + private->depth = DefaultDepthOfScreen (screen_x11->xscreen); - impl->width = width; - impl->height = height; + impl->width = WidthOfScreen (screen_x11->xscreen); + impl->height = HeightOfScreen (screen_x11->xscreen); _gdk_window_init_position (GDK_WINDOW (private)); @@ -400,7 +391,6 @@ gdk_window_new (GdkWindow *parent, XSetWindowAttributes xattributes; long xattributes_mask; XSizeHints size_hints; - XWMHints wm_hints; XClassHint *class_hint; int x, y, depth; @@ -659,19 +649,12 @@ gdk_window_new (GdkWindow *parent, check_leader_window_title (screen_x11->display); - wm_hints.flags = StateHint | WindowGroupHint; - wm_hints.window_group = GDK_DISPLAY_X11 (screen_x11->display)->leader_window; - wm_hints.input = True; - wm_hints.initial_state = NormalState; - /* FIXME: Is there any point in doing this? Do any WM's pay * attention to PSize, and even if they do, is this the * correct value??? */ XSetWMNormalHints (xdisplay, xid, &size_hints); - XSetWMHints (xdisplay, xid, &wm_hints); - /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */ XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL); @@ -855,14 +838,38 @@ _gdk_windowing_window_destroy (GdkWindow *window, gboolean foreign_destroy) { GdkWindowObject *private = (GdkWindowObject *)window; - + GdkWindowImplX11 *window_impl; + g_return_if_fail (GDK_IS_WINDOW (window)); + window_impl = GDK_WINDOW_IMPL_X11 (private->impl); + _gdk_selection_window_destroyed (window); if (private->extension_events != 0) _gdk_input_window_destroy (window); + if (window_impl->icon_window) + { + g_object_unref (window_impl->icon_window); + window_impl->icon_window = NULL; + } + if (window_impl->icon_pixmap) + { + g_object_unref (window_impl->icon_pixmap); + window_impl->icon_pixmap = NULL; + } + if (window_impl->icon_mask) + { + g_object_unref (window_impl->icon_mask); + window_impl->icon_mask = NULL; + } + if (window_impl->group_leader) + { + g_object_unref (window_impl->group_leader); + window_impl->group_leader = NULL; + } + #ifdef HAVE_XFT { GdkDrawableImplX11 *draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl); @@ -944,6 +951,61 @@ gdk_window_destroy_notify (GdkWindow *window) g_object_unref (window); } +static void +update_wm_hints (GdkWindow *window, + gboolean force) +{ + GdkWindowObject *private = (GdkWindowObject *)window; + GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl); + GdkDisplay *display = GDK_WINDOW_DISPLAY (window); + XWMHints wm_hints; + + if (!force && + private->state & GDK_WINDOW_STATE_WITHDRAWN) + return; + + wm_hints.flags = StateHint; + wm_hints.input = True; + wm_hints.initial_state = NormalState; + + if (private->state & GDK_WINDOW_STATE_ICONIFIED) + { + wm_hints.flags |= StateHint; + wm_hints.initial_state = IconicState; + } + + if (impl->icon_window && !GDK_WINDOW_DESTROYED (impl->icon_window)) + { + wm_hints.flags |= IconWindowHint; + wm_hints.icon_window = GDK_WINDOW_XID (impl->icon_window); + } + + if (impl->icon_pixmap) + { + wm_hints.flags |= IconPixmapHint; + wm_hints.icon_pixmap = GDK_PIXMAP_XID (impl->icon_pixmap); + } + + if (impl->icon_mask) + { + wm_hints.flags |= IconMaskHint; + wm_hints.icon_mask = GDK_PIXMAP_XID (impl->icon_mask); + } + + wm_hints.flags |= WindowGroupHint; + if (impl->group_leader && !GDK_WINDOW_DESTROYED (impl->group_leader)) + { + wm_hints.flags |= WindowGroupHint; + wm_hints.window_group = GDK_WINDOW_XID (impl->group_leader); + } + else + wm_hints.window_group = GDK_DISPLAY_X11 (display)->leader_window; + + XSetWMHints (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + &wm_hints); +} + static void set_initial_hints (GdkWindow *window) { @@ -957,22 +1019,9 @@ set_initial_hints (GdkWindow *window) private = (GdkWindowObject*) window; impl = GDK_WINDOW_IMPL_X11 (private->impl); + + update_wm_hints (window, TRUE); - if (private->state & GDK_WINDOW_STATE_ICONIFIED) - { - XWMHints *wm_hints; - - wm_hints = XGetWMHints (xdisplay, xwindow); - if (!wm_hints) - wm_hints = XAllocWMHints (); - - wm_hints->flags |= StateHint; - wm_hints->initial_state = IconicState; - - XSetWMHints (xdisplay, xwindow, wm_hints); - XFree (wm_hints); - } - /* We set the spec hints regardless of whether the spec is supported, * since it can't hurt and it's kind of expensive to check whether * it's supported. @@ -1068,9 +1117,12 @@ show_window_internal (GdkWindow *window, private = (GdkWindowObject*) window; if (!private->destroyed) { + GdkWindowImplX11 *impl =GDK_WINDOW_IMPL_X11 (private->impl); + Display *xdisplay = GDK_WINDOW_XDISPLAY (window); + Window xwindow = GDK_WINDOW_XID (window); + if (raise) - XRaiseWindow (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window)); + XRaiseWindow (xdisplay, xwindow); if (!GDK_WINDOW_IS_MAPPED (window)) { @@ -1079,13 +1131,14 @@ show_window_internal (GdkWindow *window, gdk_synthesize_window_state (window, GDK_WINDOW_STATE_WITHDRAWN, 0); + + impl->map_serial = NextRequest (xdisplay); } g_assert (GDK_WINDOW_IS_MAPPED (window)); - - if (GDK_WINDOW_IMPL_X11 (private->impl)->position_info.mapped) - XMapWindow (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window)); + + if (impl->position_info.mapped) + XMapWindow (xdisplay, xwindow); } } @@ -1550,11 +1603,15 @@ void gdk_window_focus (GdkWindow *window, guint32 timestamp) { + GdkDisplay *display; + g_return_if_fail (GDK_IS_WINDOW (window)); if (GDK_WINDOW_DESTROYED (window)) return; + display = GDK_WINDOW_DISPLAY (window); + if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window), gdk_atom_intern ("_NET_ACTIVE_WINDOW", FALSE))) { @@ -1564,7 +1621,7 @@ gdk_window_focus (GdkWindow *window, xev.xclient.serial = 0; xev.xclient.send_event = True; xev.xclient.window = GDK_WINDOW_XWINDOW (window); - xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), + xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_ACTIVE_WINDOW"); xev.xclient.format = 32; xev.xclient.data.l[0] = 0; @@ -1573,24 +1630,20 @@ gdk_window_focus (GdkWindow *window, xev.xclient.data.l[3] = 0; xev.xclient.data.l[4] = 0; - XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False, + XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); } else { - XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window)); + XRaiseWindow (GDK_DISPLAY_XDISPLAY (window), GDK_WINDOW_XID (window)); - /* There is no way of knowing reliably whether we are viewable so we need - * to trap errors so we don't cause a BadMatch. + /* There is no way of knowing reliably whether we are viewable; + * _gdk_x11_set_input_focus_safe() traps errors asynchronously. */ - gdk_error_trap_push (); - XSetInputFocus (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XWINDOW (window), - RevertToParent, - timestamp); - XSync (GDK_WINDOW_XDISPLAY (window), False); - gdk_error_trap_pop (); + _gdk_x11_set_input_focus_safe (display, GDK_WINDOW_XID (window), + RevertToParent, + timestamp); } } @@ -3277,40 +3330,40 @@ gdk_window_set_icon (GdkWindow *window, GdkPixmap *pixmap, GdkBitmap *mask) { - XWMHints *wm_hints; - + GdkWindowObject *private; + GdkWindowImplX11 *impl; + g_return_if_fail (window != NULL); g_return_if_fail (GDK_IS_WINDOW (window)); if (GDK_WINDOW_DESTROYED (window)) return; - wm_hints = XGetWMHints (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window)); - if (!wm_hints) - wm_hints = XAllocWMHints (); + private = (GdkWindowObject *)window; + impl = GDK_WINDOW_IMPL_X11 (private->impl); - if (icon_window != NULL) + if (impl->icon_window != icon_window) { - wm_hints->flags |= IconWindowHint; - wm_hints->icon_window = GDK_WINDOW_XID (icon_window); + if (impl->icon_window) + g_object_unref (impl->icon_window); + impl->icon_window = g_object_ref (icon_window); } - if (pixmap != NULL) + if (impl->icon_pixmap != pixmap) { - wm_hints->flags |= IconPixmapHint; - wm_hints->icon_pixmap = GDK_PIXMAP_XID (pixmap); + if (impl->icon_pixmap) + g_object_unref (impl->icon_pixmap); + impl->icon_pixmap = g_object_ref (pixmap); } - if (mask != NULL) + if (impl->icon_mask != mask) { - wm_hints->flags |= IconMaskHint; - wm_hints->icon_mask = GDK_PIXMAP_XID (mask); + if (impl->icon_mask) + g_object_unref (impl->icon_mask); + impl->icon_mask = g_object_ref (mask); } - - XSetWMHints (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), wm_hints); - XFree (wm_hints); + + update_wm_hints (window, FALSE); } static gboolean @@ -3733,15 +3786,13 @@ gdk_window_unfullscreen (GdkWindow *window) * allow users to minimize/unminimize all windows belonging to an * application at once. You should only set a non-default group window * if your application pretends to be multiple applications. - * The group leader window may not be changed after a window has been - * mapped (with gdk_window_show() for example). - * **/ void gdk_window_set_group (GdkWindow *window, GdkWindow *leader) { - XWMHints *wm_hints; + GdkWindowObject *private; + GdkWindowImplX11 *impl; g_return_if_fail (window != NULL); g_return_if_fail (GDK_IS_WINDOW (window)); @@ -3751,17 +3802,17 @@ gdk_window_set_group (GdkWindow *window, if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (leader)) return; - wm_hints = XGetWMHints (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window)); - if (!wm_hints) - wm_hints = XAllocWMHints (); + private = (GdkWindowObject *)window; + impl = GDK_WINDOW_IMPL_X11 (private->impl); - wm_hints->flags |= WindowGroupHint; - wm_hints->window_group = GDK_WINDOW_XID (leader); + if (impl->group_leader != leader) + { + if (impl->group_leader) + g_object_unref (impl->group_leader); + impl->group_leader = g_object_ref (impl->group_leader); + } - XSetWMHints (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), wm_hints); - XFree (wm_hints); + update_wm_hints (window, FALSE); } static MotifWmHints * diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h index 72246ebf23..105676075e 100644 --- a/gdk/x11/gdkwindow-x11.h +++ b/gdk/x11/gdkwindow-x11.h @@ -90,7 +90,21 @@ struct _GdkWindowImplX11 /* Set if we are requesting these hints */ guint skip_taskbar_hint : 1; guint skip_pager_hint : 1; + + guint on_all_desktops : 1; /* _NET_WM_STICKY == 0xFFFFFFFF */ + + guint have_sticky : 1; /* _NET_WM_STATE_STICKY */ + guint have_maxvert : 1; /* _NET_WM_STATE_MAXIMIZED_VERT */ + guint have_maxhorz : 1; /* _NET_WM_STATE_MAXIMIZED_HORZ */ + guint have_fullscreen : 1; /* _NET_WM_STATE_FULLSCREEN */ + + gulong map_serial; /* Serial of last transition from unmapped */ + GdkPixmap *icon_pixmap; + GdkPixmap *icon_mask; + GdkPixmap *icon_window; + GdkWindow *group_leader; + /* We use an extra X window for toplevel windows that we XSetInputFocus() * to in order to avoid getting keyboard events redirected to subwindows * that might not even be part of this app diff --git a/gdk/x11/xsettings-client.c b/gdk/x11/xsettings-client.c index 7be2dd1bb4..542e9cfaf4 100644 --- a/gdk/x11/xsettings-client.c +++ b/gdk/x11/xsettings-client.c @@ -439,7 +439,9 @@ xsettings_client_new (Display *display, { XSettingsClient *client; char buffer[256]; - + char *atom_names[3]; + Atom atoms[3]; + client = malloc (sizeof *client); if (!client) return NULL; @@ -454,9 +456,15 @@ xsettings_client_new (Display *display, client->settings = NULL; sprintf(buffer, "_XSETTINGS_S%d", screen); - client->selection_atom = XInternAtom (display, buffer, False); - client->xsettings_atom = XInternAtom (display, "_XSETTINGS_SETTINGS", False); - client->manager_atom = XInternAtom (display, "MANAGER", False); + atom_names[0] = buffer; + atom_names[1] = "_XSETTINGS_SETTINGS"; + atom_names[2] = "MANAGER"; + + XInternAtoms (display, atom_names, 3, False, atoms); + + client->selection_atom = atoms[0]; + client->xsettings_atom = atoms[1]; + client->manager_atom = atoms[2]; /* Select on StructureNotify so we get MANAGER events */