gtk/gdk/gdk.c
CST 1999 Shawn T. Amundson 279e878bdd Added notice to look in AUTHORS and ChangeLog files for a list of changes.
Wed Feb 24 01:22:39 CST 1999 Shawn T. Amundson <amundson@gtk.org>

        * *.[ch]: Added notice to look in AUTHORS and ChangeLog files
	  for a list of changes.
1999-02-24 07:37:18 +00:00

1386 lines
32 KiB
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 Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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-1999. 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 <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif /* HAVE_SYS_SELECT_H_ */
#define XLIB_ILLEGAL_ACCESS
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xos.h>
#include <X11/Xutil.h>
#include <X11/Xmu/WinUtil.h>
#include <X11/cursorfont.h>
#include "gdk.h"
#include "gdkprivate.h"
#include "gdkinput.h"
#include "gdkx.h"
#include "gdki18n.h"
#ifndef X_GETTIMEOFDAY
#define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL)
#endif /* X_GETTIMEOFDAY */
typedef struct _GdkPredicate GdkPredicate;
typedef struct _GdkErrorTrap GdkErrorTrap;
struct _GdkPredicate
{
GdkEventFunc func;
gpointer data;
};
struct _GdkErrorTrap
{
gint error_warnings;
gint error_code;
};
/*
* Private function declarations
*/
#ifndef HAVE_XCONVERTCASE
static void gdkx_XConvertCase (KeySym symbol,
KeySym *lower,
KeySym *upper);
#define XConvertCase gdkx_XConvertCase
#endif
static void gdk_exit_func (void);
static int gdk_x_error (Display *display,
XErrorEvent *error);
static int gdk_x_io_error (Display *display);
GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
GdkEvent *event,
gpointer data);
/* Private variable declarations
*/
static int gdk_initialized = 0; /* 1 if the library is initialized,
* 0 otherwise.
*/
static struct timeval start; /* The time at which the library was
* last initialized.
*/
static struct timeval timer; /* Timeout interval to use in the call
* to "select". This is used in
* conjunction with "timerp" to create
* a maximum time to wait for an event
* to arrive.
*/
static struct timeval *timerp; /* The actual timer passed to "select"
* This may be NULL, in which case
* "select" will block until an event
* arrives.
*/
static guint32 timer_val; /* The timeout length as specified by
* the user in milliseconds.
*/
static gint autorepeat;
static GSList *gdk_error_traps = NULL; /* List of error traps */
static GSList *gdk_error_trap_free_list = NULL; /* Free list */
#ifdef G_ENABLE_DEBUG
static const GDebugKey gdk_debug_keys[] = {
{"events", GDK_DEBUG_EVENTS},
{"misc", GDK_DEBUG_MISC},
{"dnd", GDK_DEBUG_DND},
{"color-context", GDK_DEBUG_COLOR_CONTEXT},
{"xim", GDK_DEBUG_XIM}
};
static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
#endif /* G_ENABLE_DEBUG */
/*
*--------------------------------------------------------------
* gdk_init_heck
*
* Initialize the library for use.
*
* Arguments:
* "argc" is the number of arguments.
* "argv" is an array of strings.
*
* Results:
* "argc" and "argv" are modified to reflect any arguments
* which were not handled. (Such arguments should either
* be handled by the application or dismissed). If initialization
* fails, returns FALSE, otherwise TRUE.
*
* Side effects:
* The library is initialized.
*
*--------------------------------------------------------------
*/
gboolean
gdk_init_check (int *argc,
char ***argv)
{
XKeyboardState keyboard_state;
gint synchronize;
gint i, j, k;
XClassHint *class_hint;
gchar **argv_orig = NULL;
gint argc_orig = 0;
if (gdk_initialized)
return TRUE;
if (g_thread_supported ())
gdk_threads_mutex = g_mutex_new ();
if (argc && argv)
{
argc_orig = *argc;
argv_orig = g_malloc ((argc_orig + 1) * sizeof (char*));
for (i = 0; i < argc_orig; i++)
argv_orig[i] = g_strdup ((*argv)[i]);
argv_orig[argc_orig] = NULL;
}
X_GETTIMEOFDAY (&start);
gdk_display_name = NULL;
XSetErrorHandler (gdk_x_error);
XSetIOErrorHandler (gdk_x_io_error);
synchronize = FALSE;
#ifdef G_ENABLE_DEBUG
{
gchar *debug_string = getenv("GDK_DEBUG");
if (debug_string != NULL)
gdk_debug_flags = g_parse_debug_string (debug_string,
(GDebugKey *) gdk_debug_keys,
gdk_ndebug_keys);
}
#endif /* G_ENABLE_DEBUG */
if (argc && argv)
{
if (*argc > 0)
{
gchar *d;
d = strrchr((*argv)[0],'/');
if (d != NULL)
g_set_prgname (d + 1);
else
g_set_prgname ((*argv)[0]);
}
for (i = 1; i < *argc;)
{
#ifdef G_ENABLE_DEBUG
if ((strcmp ("--gdk-debug", (*argv)[i]) == 0) ||
(strncmp ("--gdk-debug=", (*argv)[i], 12) == 0))
{
gchar *equal_pos = strchr ((*argv)[i], '=');
if (equal_pos != NULL)
{
gdk_debug_flags |= g_parse_debug_string (equal_pos+1,
(GDebugKey *) gdk_debug_keys,
gdk_ndebug_keys);
}
else if ((i + 1) < *argc && (*argv)[i + 1])
{
gdk_debug_flags |= g_parse_debug_string ((*argv)[i+1],
(GDebugKey *) gdk_debug_keys,
gdk_ndebug_keys);
(*argv)[i] = NULL;
i += 1;
}
(*argv)[i] = NULL;
}
else if ((strcmp ("--gdk-no-debug", (*argv)[i]) == 0) ||
(strncmp ("--gdk-no-debug=", (*argv)[i], 15) == 0))
{
gchar *equal_pos = strchr ((*argv)[i], '=');
if (equal_pos != NULL)
{
gdk_debug_flags &= ~g_parse_debug_string (equal_pos+1,
(GDebugKey *) gdk_debug_keys,
gdk_ndebug_keys);
}
else if ((i + 1) < *argc && (*argv)[i + 1])
{
gdk_debug_flags &= ~g_parse_debug_string ((*argv)[i+1],
(GDebugKey *) gdk_debug_keys,
gdk_ndebug_keys);
(*argv)[i] = NULL;
i += 1;
}
(*argv)[i] = NULL;
}
else
#endif /* G_ENABLE_DEBUG */
if (strcmp ("--display", (*argv)[i]) == 0)
{
(*argv)[i] = NULL;
if ((i + 1) < *argc && (*argv)[i + 1])
{
gdk_display_name = g_strdup ((*argv)[i + 1]);
(*argv)[i + 1] = NULL;
i += 1;
}
}
else if (strcmp ("--sync", (*argv)[i]) == 0)
{
(*argv)[i] = NULL;
synchronize = TRUE;
}
else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
{
(*argv)[i] = NULL;
gdk_use_xshm = FALSE;
}
else if (strcmp ("--name", (*argv)[i]) == 0)
{
if ((i + 1) < *argc && (*argv)[i + 1])
{
(*argv)[i++] = NULL;
g_set_prgname ((*argv)[i]);
(*argv)[i] = NULL;
}
}
else if (strcmp ("--class", (*argv)[i]) == 0)
{
if ((i + 1) < *argc && (*argv)[i + 1])
{
(*argv)[i++] = NULL;
gdk_progclass = (*argv)[i];
(*argv)[i] = NULL;
}
}
#ifdef XINPUT_GXI
else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
{
if ((i + 1) < *argc && (*argv)[i + 1])
{
(*argv)[i++] = NULL;
gdk_input_gxid_host = ((*argv)[i]);
(*argv)[i] = NULL;
}
}
else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
{
if ((i + 1) < *argc && (*argv)[i + 1])
{
(*argv)[i++] = NULL;
gdk_input_gxid_port = atoi ((*argv)[i]);
(*argv)[i] = NULL;
}
}
#endif
#ifdef USE_XIM
else if (strcmp ("--xim-preedit", (*argv)[i]) == 0)
{
if ((i + 1) < *argc && (*argv)[i + 1])
{
(*argv)[i++] = NULL;
if (strcmp ("none", (*argv)[i]) == 0)
gdk_im_set_best_style (GDK_IM_PREEDIT_NONE);
else if (strcmp ("nothing", (*argv)[i]) == 0)
gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING);
else if (strcmp ("area", (*argv)[i]) == 0)
gdk_im_set_best_style (GDK_IM_PREEDIT_AREA);
else if (strcmp ("position", (*argv)[i]) == 0)
gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION);
else if (strcmp ("callbacks", (*argv)[i]) == 0)
gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
}
}
else if (strcmp ("--xim-status", (*argv)[i]) == 0)
{
if ((i + 1) < *argc && (*argv)[i + 1])
{
(*argv)[i++] = NULL;
if (strcmp ("none", (*argv)[i]) == 0)
gdk_im_set_best_style (GDK_IM_STATUS_NONE);
else if (strcmp ("nothing", (*argv)[i]) == 0)
gdk_im_set_best_style (GDK_IM_STATUS_NOTHING);
else if (strcmp ("area", (*argv)[i]) == 0)
gdk_im_set_best_style (GDK_IM_STATUS_AREA);
else if (strcmp ("callbacks", (*argv)[i]) == 0)
gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
}
}
#endif
i += 1;
}
for (i = 1; i < *argc; i++)
{
for (k = i; k < *argc; k++)
if ((*argv)[k] != NULL)
break;
if (k > i)
{
k -= i;
for (j = i + k; j < *argc; j++)
(*argv)[j-k] = (*argv)[j];
*argc -= k;
}
}
}
else
{
g_set_prgname ("<unknown>");
}
GDK_NOTE (MISC, g_message ("progname: \"%s\"", g_get_prgname ()));
gdk_display = XOpenDisplay (gdk_display_name);
if (!gdk_display)
return FALSE;
if (synchronize)
XSynchronize (gdk_display, True);
gdk_screen = DefaultScreen (gdk_display);
gdk_root_window = RootWindow (gdk_display, gdk_screen);
gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
10, 10, 10, 10, 0, 0 , 0);
class_hint = XAllocClassHint();
class_hint->res_name = g_get_prgname ();
if (gdk_progclass == NULL)
{
gdk_progclass = g_strdup (g_get_prgname ());
gdk_progclass[0] = toupper (gdk_progclass[0]);
}
class_hint->res_class = gdk_progclass;
XmbSetWMProperties (gdk_display, gdk_leader_window,
NULL, NULL, argv_orig, argc_orig,
NULL, NULL, class_hint);
XFree (class_hint);
for (i = 0; i < argc_orig; i++)
g_free(argv_orig[i]);
g_free(argv_orig);
gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
gdk_wm_window_protocols[0] = gdk_wm_delete_window;
gdk_wm_window_protocols[1] = gdk_wm_take_focus;
gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
XGetKeyboardControl (gdk_display, &keyboard_state);
autorepeat = keyboard_state.global_auto_repeat;
timer.tv_sec = 0;
timer.tv_usec = 0;
timerp = NULL;
g_atexit (gdk_exit_func);
gdk_events_init ();
gdk_visual_init ();
gdk_window_init ();
gdk_image_init ();
gdk_input_init ();
gdk_dnd_init ();
#ifdef USE_XIM
gdk_im_open ();
#endif
gdk_initialized = 1;
return TRUE;
}
void
gdk_init (int *argc, char ***argv)
{
if (!gdk_init_check (argc, argv))
{
g_warning ("cannot open display: %s", gdk_get_display ());
exit(1);
}
}
/*
*--------------------------------------------------------------
* gdk_exit
*
* Restores the library to an un-itialized state and exits
* the program using the "exit" system call.
*
* Arguments:
* "errorcode" is the error value to pass to "exit".
*
* Results:
* Allocated structures are freed and the program exits
* cleanly.
*
* Side effects:
*
*--------------------------------------------------------------
*/
void
gdk_exit (int errorcode)
{
/* de-initialisation is done by the gdk_exit_funct(),
no need to do this here (Alex J.) */
exit (errorcode);
}
void
gdk_set_use_xshm (gint use_xshm)
{
gdk_use_xshm = use_xshm;
}
gint
gdk_get_use_xshm (void)
{
return gdk_use_xshm;
}
/*
*--------------------------------------------------------------
* gdk_time_get
*
* Get the number of milliseconds since the library was
* initialized.
*
* Arguments:
*
* Results:
* The time since the library was initialized is returned.
* This time value is accurate to milliseconds even though
* a more accurate time down to the microsecond could be
* returned.
*
* Side effects:
*
*--------------------------------------------------------------
*/
guint32
gdk_time_get (void)
{
struct timeval end;
struct timeval elapsed;
guint32 milliseconds;
X_GETTIMEOFDAY (&end);
if (start.tv_usec > end.tv_usec)
{
end.tv_usec += 1000000;
end.tv_sec--;
}
elapsed.tv_sec = end.tv_sec - start.tv_sec;
elapsed.tv_usec = end.tv_usec - start.tv_usec;
milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
return milliseconds;
}
/*
*--------------------------------------------------------------
* gdk_timer_get
*
* Returns the current timer.
*
* Arguments:
*
* Results:
* Returns the current timer interval. This interval is
* in units of milliseconds.
*
* Side effects:
*
*--------------------------------------------------------------
*/
guint32
gdk_timer_get (void)
{
return timer_val;
}
/*
*--------------------------------------------------------------
* gdk_timer_set
*
* Sets the timer interval.
*
* Arguments:
* "milliseconds" is the new value for the timer.
*
* Results:
*
* Side effects:
* Calls to "gdk_event_get" will last for a maximum
* of time of "milliseconds". However, a value of 0
* milliseconds will cause "gdk_event_get" to block
* indefinately until an event is received.
*
*--------------------------------------------------------------
*/
void
gdk_timer_set (guint32 milliseconds)
{
timer_val = milliseconds;
timer.tv_sec = milliseconds / 1000;
timer.tv_usec = (milliseconds % 1000) * 1000;
}
void
gdk_timer_enable (void)
{
timerp = &timer;
}
void
gdk_timer_disable (void)
{
timerp = NULL;
}
/*
*--------------------------------------------------------------
* gdk_pointer_grab
*
* Grabs the pointer to a specific window
*
* Arguments:
* "window" is the window which will receive the grab
* "owner_events" specifies whether events will be reported as is,
* or relative to "window"
* "event_mask" masks only interesting events
* "confine_to" limits the cursor movement to the specified window
* "cursor" changes the cursor for the duration of the grab
* "time" specifies the time
*
* Results:
*
* Side effects:
* requires a corresponding call to gdk_pointer_ungrab
*
*--------------------------------------------------------------
*/
gint
gdk_pointer_grab (GdkWindow * window,
gint owner_events,
GdkEventMask event_mask,
GdkWindow * confine_to,
GdkCursor * cursor,
guint32 time)
{
/* From gdkwindow.c */
gint return_val;
GdkWindowPrivate *window_private;
GdkWindowPrivate *confine_to_private;
GdkCursorPrivate *cursor_private;
guint xevent_mask;
Window xwindow;
Window xconfine_to;
Cursor xcursor;
int i;
g_return_val_if_fail (window != NULL, 0);
window_private = (GdkWindowPrivate*) window;
confine_to_private = (GdkWindowPrivate*) confine_to;
cursor_private = (GdkCursorPrivate*) cursor;
xwindow = window_private->xwindow;
if (!confine_to || confine_to_private->destroyed)
xconfine_to = None;
else
xconfine_to = confine_to_private->xwindow;
if (!cursor)
xcursor = None;
else
xcursor = cursor_private->xcursor;
xevent_mask = 0;
for (i = 0; i < gdk_nevent_masks; i++)
{
if (event_mask & (1 << (i + 1)))
xevent_mask |= gdk_event_mask_table[i];
}
if (gdk_input_vtable.grab_pointer)
return_val = gdk_input_vtable.grab_pointer (window,
owner_events,
event_mask,
confine_to,
time);
else
return_val = Success;
if (return_val == Success)
{
if (!window_private->destroyed)
return_val = XGrabPointer (window_private->xdisplay,
xwindow,
owner_events,
xevent_mask,
GrabModeAsync, GrabModeAsync,
xconfine_to,
xcursor,
time);
else
return_val = AlreadyGrabbed;
}
if (return_val == GrabSuccess)
gdk_xgrab_window = window_private;
return return_val;
}
/*
*--------------------------------------------------------------
* gdk_pointer_ungrab
*
* Releases any pointer grab
*
* Arguments:
*
* Results:
*
* Side effects:
*
*--------------------------------------------------------------
*/
void
gdk_pointer_ungrab (guint32 time)
{
if (gdk_input_vtable.ungrab_pointer)
gdk_input_vtable.ungrab_pointer (time);
XUngrabPointer (gdk_display, time);
gdk_xgrab_window = NULL;
}
/*
*--------------------------------------------------------------
* gdk_pointer_is_grabbed
*
* Tell wether there is an active x pointer grab in effect
*
* Arguments:
*
* Results:
*
* Side effects:
*
*--------------------------------------------------------------
*/
gint
gdk_pointer_is_grabbed (void)
{
return gdk_xgrab_window != NULL;
}
/*
*--------------------------------------------------------------
* gdk_keyboard_grab
*
* Grabs the keyboard to a specific window
*
* Arguments:
* "window" is the window which will receive the grab
* "owner_events" specifies whether events will be reported as is,
* or relative to "window"
* "time" specifies the time
*
* Results:
*
* Side effects:
* requires a corresponding call to gdk_keyboard_ungrab
*
*--------------------------------------------------------------
*/
gint
gdk_keyboard_grab (GdkWindow * window,
gint owner_events,
guint32 time)
{
GdkWindowPrivate *window_private;
Window xwindow;
g_return_val_if_fail (window != NULL, 0);
window_private = (GdkWindowPrivate*) window;
xwindow = window_private->xwindow;
if (!window_private->destroyed)
return XGrabKeyboard (window_private->xdisplay,
xwindow,
owner_events,
GrabModeAsync, GrabModeAsync,
time);
else
return AlreadyGrabbed;
}
/*
*--------------------------------------------------------------
* gdk_keyboard_ungrab
*
* Releases any keyboard grab
*
* Arguments:
*
* Results:
*
* Side effects:
*
*--------------------------------------------------------------
*/
void
gdk_keyboard_ungrab (guint32 time)
{
XUngrabKeyboard (gdk_display, time);
}
/*
*--------------------------------------------------------------
* gdk_screen_width
*
* Return the width of the screen.
*
* Arguments:
*
* Results:
*
* Side effects:
*
*--------------------------------------------------------------
*/
gint
gdk_screen_width (void)
{
gint return_val;
return_val = DisplayWidth (gdk_display, gdk_screen);
return return_val;
}
/*
*--------------------------------------------------------------
* gdk_screen_height
*
* Return the height of the screen.
*
* Arguments:
*
* Results:
*
* Side effects:
*
*--------------------------------------------------------------
*/
gint
gdk_screen_height (void)
{
gint return_val;
return_val = DisplayHeight (gdk_display, gdk_screen);
return return_val;
}
/*
*--------------------------------------------------------------
* gdk_screen_width_mm
*
* Return the width of the screen in millimeters.
*
* Arguments:
*
* Results:
*
* Side effects:
*
*--------------------------------------------------------------
*/
gint
gdk_screen_width_mm (void)
{
gint return_val;
return_val = DisplayWidthMM (gdk_display, gdk_screen);
return return_val;
}
/*
*--------------------------------------------------------------
* gdk_screen_height
*
* Return the height of the screen in millimeters.
*
* Arguments:
*
* Results:
*
* Side effects:
*
*--------------------------------------------------------------
*/
gint
gdk_screen_height_mm (void)
{
gint return_val;
return_val = DisplayHeightMM (gdk_display, gdk_screen);
return return_val;
}
/*
*--------------------------------------------------------------
* gdk_set_sm_client_id
*
* Set the SM_CLIENT_ID property on the WM_CLIENT_LEADER window
* so that the window manager can save our state using the
* X11R6 ICCCM session management protocol. A NULL value should
* be set following disconnection from the session manager to
* remove the SM_CLIENT_ID property.
*
* Arguments:
*
* "sm_client_id" specifies the client id assigned to us by the
* session manager or NULL to remove the property.
*
* Results:
*
* Side effects:
*
*--------------------------------------------------------------
*/
void
gdk_set_sm_client_id (const gchar* sm_client_id)
{
if (sm_client_id && strcmp (sm_client_id, ""))
{
XChangeProperty (gdk_display, gdk_leader_window,
gdk_atom_intern ("SM_CLIENT_ID", FALSE),
XA_STRING, 8, PropModeReplace,
sm_client_id, strlen(sm_client_id));
}
else
XDeleteProperty (gdk_display, gdk_leader_window,
gdk_atom_intern ("SM_CLIENT_ID", FALSE));
}
void
gdk_key_repeat_disable (void)
{
XAutoRepeatOff (gdk_display);
}
void
gdk_key_repeat_restore (void)
{
if (autorepeat)
XAutoRepeatOn (gdk_display);
else
XAutoRepeatOff (gdk_display);
}
void
gdk_beep (void)
{
XBell(gdk_display, 100);
}
/*
*--------------------------------------------------------------
* gdk_exit_func
*
* This is the "atexit" function that makes sure the
* library gets a chance to cleanup.
*
* Arguments:
*
* Results:
*
* Side effects:
* The library is un-initialized and the program exits.
*
*--------------------------------------------------------------
*/
static void
gdk_exit_func (void)
{
static gboolean in_gdk_exit_func = FALSE;
/* This is to avoid an infinite loop if a program segfaults in
an atexit() handler (and yes, it does happen, especially if a program
has trounced over memory too badly for even g_message to work) */
if (in_gdk_exit_func == TRUE)
return;
in_gdk_exit_func = TRUE;
if (gdk_initialized)
{
#ifdef USE_XIM
/* cleanup IC */
gdk_ic_cleanup ();
/* close IM */
gdk_im_close ();
#endif
gdk_image_exit ();
gdk_input_exit ();
gdk_key_repeat_restore ();
XCloseDisplay (gdk_display);
gdk_initialized = 0;
}
}
/*
*--------------------------------------------------------------
* gdk_x_error
*
* The X error handling routine.
*
* Arguments:
* "display" is the X display the error orignated from.
* "error" is the XErrorEvent that we are handling.
*
* Results:
* Either we were expecting some sort of error to occur,
* in which case we set the "gdk_error_code" flag, or this
* error was unexpected, in which case we will print an
* error message and exit. (Since trying to continue will
* most likely simply lead to more errors).
*
* Side effects:
*
*--------------------------------------------------------------
*/
static int
gdk_x_error (Display *display,
XErrorEvent *error)
{
char buf[64];
if (gdk_error_warnings)
{
XGetErrorText (display, error->error_code, buf, 63);
g_error ("%s\n serial %ld error_code %d request_code %d minor_code %d\n",
buf,
error->serial,
error->error_code,
error->request_code,
error->minor_code);
}
gdk_error_code = -1;
return 0;
}
/*
*--------------------------------------------------------------
* gdk_x_io_error
*
* The X I/O error handling routine.
*
* Arguments:
* "display" is the X display the error orignated from.
*
* Results:
* An X I/O error basically means we lost our connection
* to the X server. There is not much we can do to
* continue, so simply print an error message and exit.
*
* Side effects:
*
*--------------------------------------------------------------
*/
static int
gdk_x_io_error (Display *display)
{
g_error ("an x io error occurred");
return 0;
}
gchar *
gdk_get_display (void)
{
return (gchar *)XDisplayName (gdk_display_name);
}
/*************************************************************
* gdk_error_trap_push:
* Push an error trap. X errors will be trapped until
* the corresponding gdk_error_pop(), which will return
* the error code, if any.
* arguments:
*
* results:
*************************************************************/
void
gdk_error_trap_push (void)
{
GSList *node;
GdkErrorTrap *trap;
if (gdk_error_trap_free_list)
{
node = gdk_error_trap_free_list;
gdk_error_trap_free_list = gdk_error_trap_free_list->next;
}
else
{
node = g_slist_alloc();
node->data = g_new (GdkErrorTrap, 1);
}
node->next = gdk_error_traps;
gdk_error_traps = node;
trap = node->data;
trap->error_code = gdk_error_code;
trap->error_warnings = gdk_error_warnings;
gdk_error_code = 0;
gdk_error_warnings = 0;
}
/*************************************************************
* gdk_error_trap_pop:
* Pop an error trap added with gdk_error_push()
* arguments:
*
* results:
* 0, if no error occured, otherwise the error code.
*************************************************************/
gint
gdk_error_trap_pop (void)
{
GSList *node;
GdkErrorTrap *trap;
gint result;
g_return_val_if_fail (gdk_error_traps != NULL, 0);
node = gdk_error_traps;
gdk_error_traps = gdk_error_traps->next;
node->next = gdk_error_trap_free_list;
gdk_error_trap_free_list = node;
result = gdk_error_code;
trap = node->data;
gdk_error_code = trap->error_code;
gdk_error_warnings = trap->error_warnings;
return result;
}
gint
gdk_send_xevent (Window window, gboolean propagate, glong event_mask,
XEvent *event_send)
{
Status result;
gint old_warnings = gdk_error_warnings;
gdk_error_code = 0;
gdk_error_warnings = 0;
result = XSendEvent (gdk_display, window, propagate, event_mask, event_send);
XSync (gdk_display, False);
gdk_error_warnings = old_warnings;
return result && (gdk_error_code != -1);
}
#ifndef HAVE_XCONVERTCASE
/* compatibility function from X11R6.3, since XConvertCase is not
* supplied by X11R5.
*/
static void
gdkx_XConvertCase (KeySym symbol,
KeySym *lower,
KeySym *upper)
{
register KeySym sym = symbol;
g_return_if_fail (lower != NULL);
g_return_if_fail (upper != NULL);
*lower = sym;
*upper = sym;
switch (sym >> 8)
{
#if defined (GDK_A) && defined (GDK_Ooblique)
case 0: /* Latin 1 */
if ((sym >= GDK_A) && (sym <= GDK_Z))
*lower += (GDK_a - GDK_A);
else if ((sym >= GDK_a) && (sym <= GDK_z))
*upper -= (GDK_a - GDK_A);
else if ((sym >= GDK_Agrave) && (sym <= GDK_Odiaeresis))
*lower += (GDK_agrave - GDK_Agrave);
else if ((sym >= GDK_agrave) && (sym <= GDK_odiaeresis))
*upper -= (GDK_agrave - GDK_Agrave);
else if ((sym >= GDK_Ooblique) && (sym <= GDK_Thorn))
*lower += (GDK_oslash - GDK_Ooblique);
else if ((sym >= GDK_oslash) && (sym <= GDK_thorn))
*upper -= (GDK_oslash - GDK_Ooblique);
break;
#endif /* LATIN1 */
#if defined (GDK_Aogonek) && defined (GDK_tcedilla)
case 1: /* Latin 2 */
/* Assume the KeySym is a legal value (ignore discontinuities) */
if (sym == GDK_Aogonek)
*lower = GDK_aogonek;
else if (sym >= GDK_Lstroke && sym <= GDK_Sacute)
*lower += (GDK_lstroke - GDK_Lstroke);
else if (sym >= GDK_Scaron && sym <= GDK_Zacute)
*lower += (GDK_scaron - GDK_Scaron);
else if (sym >= GDK_Zcaron && sym <= GDK_Zabovedot)
*lower += (GDK_zcaron - GDK_Zcaron);
else if (sym == GDK_aogonek)
*upper = GDK_Aogonek;
else if (sym >= GDK_lstroke && sym <= GDK_sacute)
*upper -= (GDK_lstroke - GDK_Lstroke);
else if (sym >= GDK_scaron && sym <= GDK_zacute)
*upper -= (GDK_scaron - GDK_Scaron);
else if (sym >= GDK_zcaron && sym <= GDK_zabovedot)
*upper -= (GDK_zcaron - GDK_Zcaron);
else if (sym >= GDK_Racute && sym <= GDK_Tcedilla)
*lower += (GDK_racute - GDK_Racute);
else if (sym >= GDK_racute && sym <= GDK_tcedilla)
*upper -= (GDK_racute - GDK_Racute);
break;
#endif /* LATIN2 */
#if defined (GDK_Hstroke) && defined (GDK_Cabovedot)
case 2: /* Latin 3 */
/* Assume the KeySym is a legal value (ignore discontinuities) */
if (sym >= GDK_Hstroke && sym <= GDK_Hcircumflex)
*lower += (GDK_hstroke - GDK_Hstroke);
else if (sym >= GDK_Gbreve && sym <= GDK_Jcircumflex)
*lower += (GDK_gbreve - GDK_Gbreve);
else if (sym >= GDK_hstroke && sym <= GDK_hcircumflex)
*upper -= (GDK_hstroke - GDK_Hstroke);
else if (sym >= GDK_gbreve && sym <= GDK_jcircumflex)
*upper -= (GDK_gbreve - GDK_Gbreve);
else if (sym >= GDK_Cabovedot && sym <= GDK_Scircumflex)
*lower += (GDK_cabovedot - GDK_Cabovedot);
else if (sym >= GDK_cabovedot && sym <= GDK_scircumflex)
*upper -= (GDK_cabovedot - GDK_Cabovedot);
break;
#endif /* LATIN3 */
#if defined (GDK_Rcedilla) && defined (GDK_Amacron)
case 3: /* Latin 4 */
/* Assume the KeySym is a legal value (ignore discontinuities) */
if (sym >= GDK_Rcedilla && sym <= GDK_Tslash)
*lower += (GDK_rcedilla - GDK_Rcedilla);
else if (sym >= GDK_rcedilla && sym <= GDK_tslash)
*upper -= (GDK_rcedilla - GDK_Rcedilla);
else if (sym == GDK_ENG)
*lower = GDK_eng;
else if (sym == GDK_eng)
*upper = GDK_ENG;
else if (sym >= GDK_Amacron && sym <= GDK_Umacron)
*lower += (GDK_amacron - GDK_Amacron);
else if (sym >= GDK_amacron && sym <= GDK_umacron)
*upper -= (GDK_amacron - GDK_Amacron);
break;
#endif /* LATIN4 */
#if defined (GDK_Serbian_DJE) && defined (GDK_Cyrillic_yu)
case 6: /* Cyrillic */
/* Assume the KeySym is a legal value (ignore discontinuities) */
if (sym >= GDK_Serbian_DJE && sym <= GDK_Serbian_DZE)
*lower -= (GDK_Serbian_DJE - GDK_Serbian_dje);
else if (sym >= GDK_Serbian_dje && sym <= GDK_Serbian_dze)
*upper += (GDK_Serbian_DJE - GDK_Serbian_dje);
else if (sym >= GDK_Cyrillic_YU && sym <= GDK_Cyrillic_HARDSIGN)
*lower -= (GDK_Cyrillic_YU - GDK_Cyrillic_yu);
else if (sym >= GDK_Cyrillic_yu && sym <= GDK_Cyrillic_hardsign)
*upper += (GDK_Cyrillic_YU - GDK_Cyrillic_yu);
break;
#endif /* CYRILLIC */
#if defined (GDK_Greek_ALPHAaccent) && defined (GDK_Greek_finalsmallsigma)
case 7: /* Greek */
/* Assume the KeySym is a legal value (ignore discontinuities) */
if (sym >= GDK_Greek_ALPHAaccent && sym <= GDK_Greek_OMEGAaccent)
*lower += (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent);
else if (sym >= GDK_Greek_alphaaccent && sym <= GDK_Greek_omegaaccent &&
sym != GDK_Greek_iotaaccentdieresis &&
sym != GDK_Greek_upsilonaccentdieresis)
*upper -= (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent);
else if (sym >= GDK_Greek_ALPHA && sym <= GDK_Greek_OMEGA)
*lower += (GDK_Greek_alpha - GDK_Greek_ALPHA);
else if (sym >= GDK_Greek_alpha && sym <= GDK_Greek_omega &&
sym != GDK_Greek_finalsmallsigma)
*upper -= (GDK_Greek_alpha - GDK_Greek_ALPHA);
break;
#endif /* GREEK */
}
}
#endif
gchar*
gdk_keyval_name (guint keyval)
{
return XKeysymToString (keyval);
}
guint
gdk_keyval_from_name (const gchar *keyval_name)
{
g_return_val_if_fail (keyval_name != NULL, 0);
return XStringToKeysym (keyval_name);
}
guint
gdk_keyval_to_upper (guint keyval)
{
if (keyval)
{
KeySym lower_val = 0;
KeySym upper_val = 0;
XConvertCase (keyval, &lower_val, &upper_val);
return upper_val;
}
return 0;
}
guint
gdk_keyval_to_lower (guint keyval)
{
if (keyval)
{
KeySym lower_val = 0;
KeySym upper_val = 0;
XConvertCase (keyval, &lower_val, &upper_val);
return lower_val;
}
return 0;
}
gboolean
gdk_keyval_is_upper (guint keyval)
{
if (keyval)
{
KeySym lower_val = 0;
KeySym upper_val = 0;
XConvertCase (keyval, &lower_val, &upper_val);
return upper_val == keyval;
}
return TRUE;
}
gboolean
gdk_keyval_is_lower (guint keyval)
{
if (keyval)
{
KeySym lower_val = 0;
KeySym upper_val = 0;
XConvertCase (keyval, &lower_val, &upper_val);
return lower_val == keyval;
}
return TRUE;
}
void
gdk_threads_enter ()
{
GDK_THREADS_ENTER ();
}
void
gdk_threads_leave ()
{
GDK_THREADS_LEAVE ();
}