Blame gtk/gtkxembed.c

Packit 98cdb6
/* GTK - The GIMP Toolkit
Packit 98cdb6
 * gtkxembed.c: Utilities for the XEMBED protocol
Packit 98cdb6
 * Copyright (C) 2001, 2003, Red Hat, Inc.
Packit 98cdb6
 *
Packit 98cdb6
 * This library is free software; you can redistribute it and/or
Packit 98cdb6
 * modify it under the terms of the GNU Lesser General Public
Packit 98cdb6
 * License as published by the Free Software Foundation; either
Packit 98cdb6
 * version 2 of the License, or (at your option) any later version.
Packit 98cdb6
 *
Packit 98cdb6
 * This library is distributed in the hope that it will be useful,
Packit 98cdb6
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 98cdb6
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 98cdb6
 * Lesser General Public License for more details.
Packit 98cdb6
 *
Packit 98cdb6
 * You should have received a copy of the GNU Lesser General Public
Packit 98cdb6
 * License along with this library; if not, write to the
Packit 98cdb6
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit 98cdb6
 * Boston, MA 02111-1307, USA.
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
#include "config.h"
Packit 98cdb6
#include <string.h>
Packit 98cdb6
#include "gtkmain.h"
Packit 98cdb6
#include "gtkprivate.h"
Packit 98cdb6
#include "gtkxembed.h"
Packit 98cdb6
#include "gtkalias.h"
Packit 98cdb6
Packit 98cdb6
typedef struct _GtkXEmbedMessage GtkXEmbedMessage;
Packit 98cdb6
Packit 98cdb6
struct _GtkXEmbedMessage
Packit 98cdb6
{
Packit 98cdb6
  glong      message;
Packit 98cdb6
  glong      detail;
Packit 98cdb6
  glong      data1;
Packit 98cdb6
  glong      data2;
Packit 98cdb6
  guint32    time;
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static GSList *current_messages;
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * _gtk_xembed_push_message:
Packit 98cdb6
 * @xevent: a XEvent
Packit 98cdb6
 * 
Packit 98cdb6
 * Adds a client message to the stack of current XEMBED events.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
_gtk_xembed_push_message (XEvent *xevent)
Packit 98cdb6
{
Packit 98cdb6
  GtkXEmbedMessage *message = g_slice_new (GtkXEmbedMessage);
Packit 98cdb6
  
Packit 98cdb6
  message->time = xevent->xclient.data.l[0];
Packit 98cdb6
  message->message = xevent->xclient.data.l[1];
Packit 98cdb6
  message->detail = xevent->xclient.data.l[2];
Packit 98cdb6
  message->data1 = xevent->xclient.data.l[3];
Packit 98cdb6
  message->data2 = xevent->xclient.data.l[4];
Packit 98cdb6
Packit 98cdb6
  current_messages = g_slist_prepend (current_messages, message);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * _gtk_xembed_pop_message:
Packit 98cdb6
 * 
Packit 98cdb6
 * Removes an event added with _gtk_xembed_push_message()
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
_gtk_xembed_pop_message (void)
Packit 98cdb6
{
Packit 98cdb6
  GtkXEmbedMessage *message = current_messages->data;
Packit 98cdb6
  current_messages = g_slist_delete_link (current_messages, current_messages);
Packit 98cdb6
  g_slice_free (GtkXEmbedMessage, message);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * _gtk_xembed_set_focus_wrapped:
Packit 98cdb6
 * 
Packit 98cdb6
 * Sets a flag indicating that the current focus sequence wrapped
Packit 98cdb6
 * around to the beginning of the ultimate toplevel.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
_gtk_xembed_set_focus_wrapped (void)
Packit 98cdb6
{
Packit 98cdb6
  GtkXEmbedMessage *message;
Packit 98cdb6
  
Packit 98cdb6
  g_return_if_fail (current_messages != NULL);
Packit 98cdb6
  message = current_messages->data;
Packit 98cdb6
  g_return_if_fail (message->message == XEMBED_FOCUS_PREV || message->message == XEMBED_FOCUS_NEXT);
Packit 98cdb6
  
Packit 98cdb6
  message->data1 |= XEMBED_FOCUS_WRAPAROUND;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * _gtk_xembed_get_focus_wrapped:
Packit 98cdb6
 * 
Packit 98cdb6
 * Gets whether the current focus sequence has wrapped around
Packit 98cdb6
 * to the beginning of the ultimate toplevel.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: %TRUE if the focus sequence has wrapped around.
Packit 98cdb6
 **/
Packit 98cdb6
gboolean
Packit 98cdb6
_gtk_xembed_get_focus_wrapped (void)
Packit 98cdb6
{
Packit 98cdb6
  GtkXEmbedMessage *message;
Packit 98cdb6
  
Packit 98cdb6
  g_return_val_if_fail (current_messages != NULL, FALSE);
Packit 98cdb6
  message = current_messages->data;
Packit 98cdb6
Packit 98cdb6
  return (message->data1 & XEMBED_FOCUS_WRAPAROUND) != 0;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static guint32
Packit 98cdb6
gtk_xembed_get_time (void)
Packit 98cdb6
{
Packit 98cdb6
  if (current_messages)
Packit 98cdb6
    {
Packit 98cdb6
      GtkXEmbedMessage *message = current_messages->data;
Packit 98cdb6
      return message->time;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    return gtk_get_current_event_time ();
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * _gtk_xembed_send_message:
Packit 98cdb6
 * @recipient: (allow-none): window to which to send the window, or %NULL
Packit 98cdb6
 *             in which case nothing will be sent
Packit 98cdb6
 * @message:   type of message
Packit 98cdb6
 * @detail:    detail field of message
Packit 98cdb6
 * @data1:     data1 field of message
Packit 98cdb6
 * @data2:     data2 field of message
Packit 98cdb6
 * 
Packit 98cdb6
 * Sends a generic XEMBED message to a particular window.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
_gtk_xembed_send_message (GdkWindow        *recipient,
Packit 98cdb6
			  XEmbedMessageType message,
Packit 98cdb6
			  glong             detail,
Packit 98cdb6
			  glong             data1,
Packit 98cdb6
			  glong             data2)
Packit 98cdb6
{
Packit 98cdb6
  GdkDisplay *display;
Packit 98cdb6
  XClientMessageEvent xclient;
Packit 98cdb6
Packit 98cdb6
  if (!recipient)
Packit 98cdb6
    return;
Packit 98cdb6
	  
Packit 98cdb6
  g_return_if_fail (GDK_IS_WINDOW (recipient));
Packit 98cdb6
Packit 98cdb6
  display = gdk_window_get_display (recipient);
Packit 98cdb6
  GTK_NOTE (PLUGSOCKET,
Packit 98cdb6
	    g_message ("Sending %s", _gtk_xembed_message_name (message)));
Packit 98cdb6
Packit 98cdb6
  memset (&xclient, 0, sizeof (xclient));
Packit 98cdb6
  xclient.window = GDK_WINDOW_XWINDOW (recipient);
Packit 98cdb6
  xclient.type = ClientMessage;
Packit 98cdb6
  xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED");
Packit 98cdb6
  xclient.format = 32;
Packit 98cdb6
  xclient.data.l[0] = gtk_xembed_get_time ();
Packit 98cdb6
  xclient.data.l[1] = message;
Packit 98cdb6
  xclient.data.l[2] = detail;
Packit 98cdb6
  xclient.data.l[3] = data1;
Packit 98cdb6
  xclient.data.l[4] = data2;
Packit 98cdb6
Packit 98cdb6
  gdk_error_trap_push ();
Packit 98cdb6
  XSendEvent (GDK_WINDOW_XDISPLAY(recipient),
Packit 98cdb6
	      GDK_WINDOW_XWINDOW (recipient),
Packit 98cdb6
	      False, NoEventMask, (XEvent *)&xclient);
Packit 98cdb6
  gdk_display_sync (display);
Packit 98cdb6
  gdk_error_trap_pop ();
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * _gtk_xembed_send_focus_message:
Packit 98cdb6
 * @recipient: (allow-none): window to which to send the window, or %NULL
Packit 98cdb6
 *             in which case nothing will be sent
Packit 98cdb6
 * @message:   type of message
Packit 98cdb6
 * @detail:    detail field of message
Packit 98cdb6
 * 
Packit 98cdb6
 * Sends a XEMBED message for moving the focus along the focus
Packit 98cdb6
 * chain to a window. The flags field that these messages share
Packit 98cdb6
 * will be correctly filled in.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
_gtk_xembed_send_focus_message (GdkWindow        *recipient,
Packit 98cdb6
				XEmbedMessageType message,
Packit 98cdb6
				glong             detail)
Packit 98cdb6
{
Packit 98cdb6
  gulong flags = 0;
Packit 98cdb6
Packit 98cdb6
  if (!recipient)
Packit 98cdb6
    return;
Packit 98cdb6
  
Packit 98cdb6
  g_return_if_fail (GDK_IS_WINDOW (recipient));
Packit 98cdb6
  g_return_if_fail (message == XEMBED_FOCUS_IN ||
Packit 98cdb6
		    message == XEMBED_FOCUS_NEXT ||
Packit 98cdb6
		    message == XEMBED_FOCUS_PREV);
Packit 98cdb6
		    
Packit 98cdb6
  if (current_messages)
Packit 98cdb6
    {
Packit 98cdb6
      GtkXEmbedMessage *message = current_messages->data;
Packit 98cdb6
      switch (message->message)
Packit 98cdb6
	{
Packit 98cdb6
	case XEMBED_FOCUS_IN:
Packit 98cdb6
	case XEMBED_FOCUS_NEXT:
Packit 98cdb6
	case XEMBED_FOCUS_PREV:
Packit 98cdb6
	  flags = message->data1 & XEMBED_FOCUS_WRAPAROUND;
Packit 98cdb6
	  break;
Packit 98cdb6
	default:
Packit 98cdb6
	  break;
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  _gtk_xembed_send_message (recipient, message, detail, flags, 0);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
const char *
Packit 98cdb6
_gtk_xembed_message_name (XEmbedMessageType message)
Packit 98cdb6
{
Packit 98cdb6
  static char unk[24];
Packit 98cdb6
  
Packit 98cdb6
  switch (message)
Packit 98cdb6
    {
Packit 98cdb6
#define CASE(x) case XEMBED_##x: return "XEMBED_"#x
Packit 98cdb6
      CASE (EMBEDDED_NOTIFY);
Packit 98cdb6
      CASE (WINDOW_ACTIVATE);
Packit 98cdb6
      CASE (WINDOW_DEACTIVATE);
Packit 98cdb6
      CASE (REQUEST_FOCUS);
Packit 98cdb6
      CASE (FOCUS_IN);
Packit 98cdb6
      CASE (FOCUS_OUT);
Packit 98cdb6
      CASE (FOCUS_NEXT);
Packit 98cdb6
      CASE (FOCUS_PREV);
Packit 98cdb6
      CASE (GRAB_KEY);
Packit 98cdb6
      CASE (UNGRAB_KEY);
Packit 98cdb6
      CASE (MODALITY_ON);
Packit 98cdb6
      CASE (MODALITY_OFF);
Packit 98cdb6
      CASE (GTK_GRAB_KEY);
Packit 98cdb6
      CASE (GTK_UNGRAB_KEY);
Packit 98cdb6
#undef CASE
Packit 98cdb6
    default:
Packit 98cdb6
      snprintf (unk, 24, "UNKNOWN(%d)", message);
Packit 98cdb6
      return unk;
Packit 98cdb6
    }
Packit 98cdb6
}