// IM-2016-01-21: [[ NativeLayer ]] Place the socket window relative to its
//    container, so only the visible area (clipped by any containing groups)
//    is displayed.
void MCNativeLayerX11::doSetGeometry(const MCRectangle& p_rect)
{
	m_rect = p_rect;
	updateContainerGeometry();
	
	MCRectangle t_rect;
	t_rect = m_rect;
	t_rect.x -= m_intersect_rect.x;
	t_rect.y -= m_intersect_rect.y;
	
    // Move the overlay window first, to ensure events don't get stolen

    // Clear any minimum size parameters for the GTK widgets
    gtk_widget_set_size_request(GTK_WIDGET(m_socket), -1, -1);
    
    // Resize the socket
    gdk_window_move_resize(gtk_widget_get_window(GTK_WIDGET(m_socket)), t_rect.x, t_rect.y, t_rect.width, t_rect.height);
    
    // We need to set the requested minimum size in order to get in-process GTK
    // widgets to re-size automatically. Unfortunately, that is the only widget
    // category that this works for... others need to do it themselves.
    gtk_widget_set_size_request(GTK_WIDGET(m_socket), t_rect.width, t_rect.height);
    
    // Update the contained window too
    GdkWindow* t_remote;
    t_remote = gtk_socket_get_plug_window(m_socket);
    if (t_remote != NULL)
        gdk_window_move_resize(t_remote, t_rect.x, t_rect.y, t_rect.width, t_rect.height);
}
Exemple #2
0
/* If we are faking transparency with a window-relative background, force a
 * redraw of the icon. This should be called if the background changes or if
 * the child is shifted with respect to the background.
 */
void
na_tray_child_force_redraw (NaTrayChild *child)
{
  GtkWidget *widget = GTK_WIDGET (child);

  if (gtk_widget_get_mapped (widget) && child->parent_relative_bg)
    {
#if 1
      /* Sending an ExposeEvent might cause redraw problems if the
       * icon is expecting the server to clear-to-background before
       * the redraw. It should be ok for GtkStatusIcon or EggTrayIcon.
       */
      Display *xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget));
      XEvent xev;
      GdkWindow *plug_window;
      GtkAllocation allocation;

      plug_window = gtk_socket_get_plug_window (GTK_SOCKET (child));
      gtk_widget_get_allocation (widget, &allocation);

      xev.xexpose.type = Expose;
#if GTK_CHECK_VERSION (3, 0, 0)
      xev.xexpose.window = GDK_WINDOW_XID (plug_window);
#else
      xev.xexpose.window = GDK_WINDOW_XWINDOW (plug_window);
#endif
      xev.xexpose.x = 0;
      xev.xexpose.y = 0;
      xev.xexpose.width = allocation.width;
      xev.xexpose.height = allocation.height;
      xev.xexpose.count = 0;

      gdk_error_trap_push ();
      XSendEvent (GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget)),
                  xev.xexpose.window,
                  False, ExposureMask,
                  &xev);
      /* We have to sync to reliably catch errors from the XSendEvent(),
       * since that is asynchronous.
       */
      XSync (xdisplay, False);
#if GTK_CHECK_VERSION (3, 0, 0)
      gdk_error_trap_pop_ignored ();
#else
      gdk_error_trap_pop ();
#endif
#else
      /* Hiding and showing is the safe way to do it, but can result in more
       * flickering.
       */
      gdk_window_hide (widget->window);
      gdk_window_show (widget->window);
#endif
    }
}
/* FIXME: should we schedule the event or not?
static gboolean
schedule_send_client_event (gpointer data)
{
  GdkEvent *event = (GdkEvent*) data;

  gdk_event_send_client_message (event, GDK_WINDOW_XID (event->client.window));

  gdk_event_free (event);

  return FALSE;
}
*/
static void on_size_alloc (AwnAppletProxy *proxy, GtkAllocation *alloc)
{
  AwnAppletProxyPrivate *priv;
  GtkWidget *parent;
  GtkAllocation parent_alloc;
  GdkWindow *plug_win;

  g_return_if_fail (AWN_IS_APPLET_PROXY (proxy));

  priv = proxy->priv;

  parent = gtk_widget_get_parent (GTK_WIDGET (proxy));
  gtk_widget_get_allocation (parent, &parent_alloc);

  gint pos_x = alloc->x;
  gint pos_y = alloc->y;
  gint rel_x = pos_x - parent_alloc.x;
  gint rel_y = pos_y - parent_alloc.y;
  gint parent_w = parent_alloc.width;
  gint parent_h = parent_alloc.height;

  if (pos_x == priv->old_x && pos_y == priv->old_y
      && parent_w == priv->old_w && parent_h == priv->old_h) return;

  priv->old_x = pos_x;
  priv->old_y = pos_y;
  priv->old_w = parent_w;
  priv->old_h = parent_h;

  /* Only directly access the struct member if we have to. */
  plug_win = gtk_socket_get_plug_window (GTK_SOCKET (proxy));
  if (plug_win)
  {
    GdkAtom msg_type = gdk_atom_intern("_AWN_APPLET_POS_CHANGE", FALSE);
    GdkEvent *event = gdk_event_new (GDK_CLIENT_EVENT);
    event->client.window = g_object_ref (plug_win);
    event->client.data_format = 32;
    event->client.message_type = msg_type;
    // first two longs are our relative [x, y]
    event->client.data.l[0] = rel_x;
    event->client.data.l[1] = rel_y;
    // other two longs are our parent's [w, h]
    event->client.data.l[2] = parent_w;
    event->client.data.l[3] = parent_h;

    gdk_event_send_client_message (event, GDK_WINDOW_XID (plug_win));

    gdk_event_free (event);
    /* g_idle_add (schedule_send_client_event, event); */
  }
}
static void
cinnamon_tray_icon_constructed (GObject *object)
{
  GdkWindow *icon_app_window;
  CinnamonTrayIcon *icon = CINNAMON_TRAY_ICON (object);
  CinnamonEmbeddedWindow *window;
  GdkDisplay *display;
  Window plug_xid;
  Atom _NET_WM_PID, type;
  int result, format;
  gulong nitems, bytes_after, *val = NULL;

  /* We do all this now rather than computing it on the fly later,
   * because Cinnamon may want to see their values from a
   * tray-icon-removed signal handler, at which point the plug has
   * already been removed from the socket.
   */

  g_object_get (object, "window", &window, NULL);
  g_return_if_fail (window != NULL);
  icon->priv->socket = NA_TRAY_CHILD (gtk_bin_get_child (GTK_BIN (window)));
  g_object_unref (window);

  icon->priv->title = na_tray_child_get_title (icon->priv->socket);
  na_tray_child_get_wm_class (icon->priv->socket, NULL, &icon->priv->wm_class);

  icon_app_window = gtk_socket_get_plug_window (GTK_SOCKET (icon->priv->socket));
  if (icon_app_window == NULL)
    {
      g_warning ("cinnamon tray: icon app window is gone");
      return;
    }
  plug_xid = GDK_WINDOW_XID (icon_app_window);

  display = gtk_widget_get_display (GTK_WIDGET (icon->priv->socket));
  gdk_error_trap_push ();
  _NET_WM_PID = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID");
  result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), plug_xid,
                               _NET_WM_PID, 0, G_MAXLONG, False, XA_CARDINAL,
                               &type, &format, &nitems,
                               &bytes_after, (guchar **)&val);
  if (!gdk_error_trap_pop () &&
      result == Success &&
      type == XA_CARDINAL &&
      nitems == 1)
    icon->priv->pid = *val;

  if (val)
    XFree (val);
}
GdkWindow *
awn_ua_alignment_add_id (AwnUAAlignment *self,GdkNativeWindow native_window)
{
  GdkWindow * plugwin;
  AwnUAAlignmentPrivate *priv;

  priv =  AWN_UA_ALIGNMENT_GET_PRIVATE (self); 
  gtk_socket_add_id (GTK_SOCKET(priv->socket), native_window);
  plugwin = gtk_socket_get_plug_window (GTK_SOCKET(priv->socket));
  g_signal_connect (priv->socket,"plug-removed",
                    G_CALLBACK(awn_ua_alignment_plug_removed),self);
  gtk_widget_realize (priv->socket);
  gtk_widget_show_all (priv->socket);
  return plugwin;
}
Exemple #6
0
static void
na_tray_manager_handle_dock_request (NaTrayManager       *manager,
				     XClientMessageEvent *xevent)
{
  Window icon_window = xevent->data.l[2];
  GtkWidget *child;

  if (g_hash_table_lookup (manager->socket_table,
                           GINT_TO_POINTER (icon_window)))
    {
      /* We already got this notification earlier, ignore this one */
      return;
    }

  child = na_tray_child_new (manager->screen, icon_window);
  if (child == NULL) /* already gone or other error */
    return;

  g_signal_emit (manager, manager_signals[TRAY_ICON_ADDED], 0,
		 child);

  /* If the child wasn't attached, then destroy it */

  if (!GTK_IS_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (child))))
    {
      gtk_widget_destroy (child);
      return;
    }

  g_signal_connect (child, "plug_removed",
		    G_CALLBACK (na_tray_manager_plug_removed), manager);

  gtk_socket_add_id (GTK_SOCKET (child), icon_window);

  if (!gtk_socket_get_plug_window (GTK_SOCKET (child)))
    {
      /* Embedding failed, we won't get a plug-removed signal */
      /* This signal destroys the socket */
      g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, child);
      return;
    }

  g_hash_table_insert (manager->socket_table,
                       GINT_TO_POINTER (icon_window), child);
  gtk_widget_show (child);
}
void MCNativeLayerX11::doAttach()
{
    if (m_socket == NULL)
    {
        // Create a new GTK socket to deal with the XEMBED protocol
        GtkSocket *t_socket;
		t_socket = GTK_SOCKET(gtk_socket_new());
        
        // Create a new GTK window to hold the socket
        MCRectangle t_rect;
        t_rect = m_object->getrect();
        m_child_window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_POPUP));
        gtk_widget_set_parent_window(GTK_WIDGET(m_child_window), getStackGdkWindow());
        gtk_widget_realize(GTK_WIDGET(m_child_window));
        gdk_window_reparent(gtk_widget_get_window(GTK_WIDGET(m_child_window)), getStackGdkWindow(), t_rect.x, t_rect.y);
        
        // Add the socket to the window
        gtk_container_add(GTK_CONTAINER(m_child_window), GTK_WIDGET(t_socket));
        
        // The socket needs to be realised before going any further or any
        // operations on it will fail.
        gtk_widget_realize(GTK_WIDGET(t_socket));
        
        // Show the socket (we'll control visibility at the window level)
        gtk_widget_show(GTK_WIDGET(t_socket));
        
        // Create an empty region to act as an input mask while in edit mode
        m_input_shape = gdk_region_new();

		// Retain a reference to the socket
		m_socket = GTK_SOCKET(g_object_ref(G_OBJECT(t_socket)));
    }
    
    // Attach the X11 window to this socket
    if (gtk_socket_get_plug_window(m_socket) == NULL)
        gtk_socket_add_id(m_socket, m_widget_xid);
    //fprintf(stderr, "XID: %u\n", gtk_socket_get_id(m_socket));
    
    // Act as if there were a re-layer to put the widget in the right place
    doRelayer();
    doSetViewportGeometry(m_viewport_rect);
    doSetGeometry(m_rect);
    doSetVisible(ShouldShowLayer());
}
static void
plug_added_cb(GtkWidget *socket, gpointer data)
{
  // The plug window has been embedded, and gtk_socket_add_window() has added
  // a filter to the socket's plug_window, passing the socket as data for the
  // filter, so the socket must live as long as events may be received on the
  // plug window.
  //
  // https://git.gnome.org/browse/gtk+/tree/gtk/gtksocket.c?h=3.18.7#n1124
  g_object_ref(socket);
  // When the socket is unrealized, perhaps during gtk_widget_destroy() from
  // ~nsPluginNativeWindowGtk, the plug is removed.  The plug in the child
  // process then destroys its widget and window.  When the browser process
  // receives the DestroyNotify event for the plug window, GDK releases its
  // reference to plugWindow.  This is typically the last reference and so the
  // weak ref callback triggers release of the socket.
  GdkWindow* plugWindow = gtk_socket_get_plug_window(GTK_SOCKET(socket));
  g_object_weak_ref(G_OBJECT(plugWindow), plug_window_finalize_cb, socket);
}
Exemple #9
0
static gint
luaH_socket_index(lua_State *L, luapdf_token_t token)
{
    widget_t *w = luaH_checkwidget(L, 1);

    switch(token)
    {
      LUAPDF_WIDGET_INDEX_COMMON

      /* push integer methods */
      PI_CASE(ID,      (int) gtk_socket_get_id(GTK_SOCKET(w->widget)))
      /* push boolean methods */
      PB_CASE(PLUGGED, gtk_socket_get_plug_window(GTK_SOCKET(w->widget))!=NULL)

      default:
        break;
    }
    return 0;
}
Exemple #10
0
/**
 * shell_tray_icon_click:
 * @icon: a #ShellTrayIcon
 * @event: the #ClutterEvent triggering the fake click
 *
 * Fakes a press and release on @icon. @event must be a
 * %CLUTTER_BUTTON_RELEASE, %CLUTTER_KEY_PRESS or %CLUTTER_KEY_RELEASE event.
 * Its relevant details will be passed on to the icon, but its
 * coordinates will be ignored; the click is
 * always made on the center of @icon.
 */
void
shell_tray_icon_click (ShellTrayIcon *icon,
                       ClutterEvent  *event)
{
  XKeyEvent xkevent;
  XButtonEvent xbevent;
  XCrossingEvent xcevent;
  GdkWindow *remote_window;
  GdkScreen *screen;
  int x_root, y_root;
  Display *xdisplay;
  Window xwindow, xrootwindow;
  ClutterEventType event_type = clutter_event_type (event);

  g_return_if_fail (event_type == CLUTTER_BUTTON_RELEASE ||
                    event_type == CLUTTER_KEY_PRESS ||
                    event_type == CLUTTER_KEY_RELEASE);

  gdk_error_trap_push ();

  remote_window = gtk_socket_get_plug_window (GTK_SOCKET (icon->priv->socket));
  xwindow = GDK_WINDOW_XID (remote_window);
  xdisplay = GDK_WINDOW_XDISPLAY (remote_window);
  screen = gdk_window_get_screen (remote_window);
  xrootwindow = GDK_WINDOW_XID (gdk_screen_get_root_window (screen));
  gdk_window_get_origin (remote_window, &x_root, &y_root);

  /* First make the icon believe the pointer is inside it */
  xcevent.type = EnterNotify;
  xcevent.window = xwindow;
  xcevent.root = xrootwindow;
  xcevent.subwindow = None;
  xcevent.time = clutter_event_get_time (event);
  xcevent.x = gdk_window_get_width (remote_window) / 2;
  xcevent.y = gdk_window_get_height (remote_window) / 2;
  xcevent.x_root = x_root + xcevent.x;
  xcevent.y_root = y_root + xcevent.y;
  xcevent.mode = NotifyNormal;
  xcevent.detail = NotifyNonlinear;
  xcevent.same_screen = True;
  XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent);

  /* Now do the click */
  if (event_type == CLUTTER_BUTTON_RELEASE)
    {
      xbevent.window = xwindow;
      xbevent.root = xrootwindow;
      xbevent.subwindow = None;
      xbevent.time = xcevent.time;
      xbevent.x = xcevent.x;
      xbevent.y = xcevent.y;
      xbevent.x_root = xcevent.x_root;
      xbevent.y_root = xcevent.y_root;
      xbevent.state = clutter_event_get_state (event);
      xbevent.same_screen = True;
      xbevent.type = ButtonPress;
      xbevent.button = clutter_event_get_button (event);
      XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent);

      xbevent.type = ButtonRelease;
      XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent);
    }
  else
    {
      xkevent.window = xwindow;
      xkevent.root = xrootwindow;
      xkevent.subwindow = None;
      xkevent.time = xcevent.time;
      xkevent.x = xcevent.x;
      xkevent.y = xcevent.y;
      xkevent.x_root = xcevent.x_root;
      xkevent.y_root = xcevent.y_root;
      xkevent.state = clutter_event_get_state (event);
      xkevent.same_screen = True;
      xkevent.keycode = clutter_event_get_key_code (event);

      xkevent.type = KeyPress;
      XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xkevent);

      if (event_type == CLUTTER_KEY_RELEASE)
        {
          /* If the application takes a grab on KeyPress, we don't
           * want to send it a KeyRelease. There's no good way of
           * knowing whether a tray icon will take a grab, so just
           * assume it does, and don't send the KeyRelease. That might
           * make the tracking for key events messed up if it doesn't take
           * a grab, but the tray icon won't get key focus in normal cases,
           * so let's hope this isn't too damaging...
           */
          xkevent.type = KeyRelease;
          XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xkevent);
        }
    }

  /* And move the pointer back out */
  xcevent.type = LeaveNotify;
  XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent);

  gdk_error_trap_pop_ignored ();
}
Exemple #11
0
static gboolean
gail_focus_watcher (GSignalInvocationHint *ihint,
                    guint                  n_param_values,
                    const GValue          *param_values,
                    gpointer               data)
{
  GObject *object;
  GtkWidget *widget;
  GdkEvent *event;

  object = g_value_get_object (param_values + 0);
  g_return_val_if_fail (GTK_IS_WIDGET(object), FALSE);

  event = g_value_get_boxed (param_values + 1);
  widget = GTK_WIDGET (object);

  if (event->type == GDK_FOCUS_CHANGE) 
    {
      if (event->focus_change.in)
        {
          if (GTK_IS_WINDOW (widget))
            {
              GtkWidget *focus_widget;
              GtkWindow *window;
              GtkWindowType type;

              window = GTK_WINDOW (widget);
              focus_widget = gtk_window_get_focus (window);
              g_object_get (window, "type", &type, NULL);

              if (focus_widget)
                {
                  /*
                   * If we already have a potential focus widget set this
                   * windows's focus widget to focus_before_menu so that 
                   * it will be reported when menu item is unset.
                   */
                  if (next_focus_widget)
                    {
                      if (GTK_IS_MENU_ITEM (next_focus_widget) &&
                          !focus_before_menu)
                        {
                          void *vp_focus_before_menu = &focus_before_menu;
                          focus_before_menu = focus_widget;
                          g_object_add_weak_pointer (G_OBJECT (focus_before_menu), vp_focus_before_menu);
                        }

                      return TRUE;
                    }
                  widget = focus_widget;
                }
              else if (type == GTK_WINDOW_POPUP)
                {
	          if (GTK_IS_BIN (widget))
		    {
		      GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));

		      if (GTK_IS_WIDGET (child) && gtk_widget_has_grab (child))
			{
			  if (GTK_IS_MENU_SHELL (child))
			    {
			      if (gtk_menu_shell_get_selected_item (GTK_MENU_SHELL (child)))
				{
				  /*
				   * We have a menu which has a menu item selected
				   * so we do not report focus on the menu.
				   */ 
				  return TRUE; 
				}
			    }
			  widget = child;
			} 
		    }
		  else /* popup window has no children; this edge case occurs in some custom code (OOo for instance) */
		    {
		      return TRUE;
		    }
                }
	      else /* Widget is a non-popup toplevel with no focus children; 
		      don't emit for this case either, as it's useless */
		{
		  return TRUE;
		}
            }
        }
      else
        {
          if (next_focus_widget)
            {
               GtkWidget *toplevel;

               toplevel = gtk_widget_get_toplevel (next_focus_widget);
               if (toplevel == widget)
                 next_focus_widget = NULL; 
            }
          /* focus out */
          widget = NULL;
        }
    }
  else
    {
      if (event->type == GDK_MOTION_NOTIFY && gtk_widget_has_focus (widget))
        {
          if (widget == _focus_widget)
            {
              return TRUE;
            }
        }
      else
        {
          return TRUE;
        }
    }

#ifdef GDK_WINDOWING_X11
  /*
   * If the focus widget is a GtkSocket without a plug
   * then ignore the focus notification as the embedded
   * plug will report a focus notification.
   */
  if (GTK_IS_SOCKET (widget) &&
      gtk_socket_get_plug_window (GTK_SOCKET (widget)) != NULL)
    return TRUE;
#endif

  /*
   * The widget may not yet be visible on the screen so we wait until it is.
   */
  gail_focus_notify_when_idle (widget);
  return TRUE; 
}
/**
 * cinnamon_tray_icon_click:
 * @icon: a #CinnamonTrayIcon
 * @event: the #ClutterEvent triggering the fake click
 *
 * Fakes a press and release on @icon. @event must be a
 * %CLUTTER_BUTTON_RELEASE event. Its relevant details will be passed
 * on to the icon, but its coordinates will be ignored; the click is
 * always made on the center of @icon.
 */
void
cinnamon_tray_icon_click (CinnamonTrayIcon *icon,
                       ClutterEvent  *event)
{
  XButtonEvent xbevent;
  XCrossingEvent xcevent;
  GdkWindow *remote_window;
  GdkScreen *screen;
  int x_root, y_root;
  Display *xdisplay;
  Window xwindow, xrootwindow;

  g_return_if_fail (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE);

  gdk_error_trap_push ();

  remote_window = gtk_socket_get_plug_window (GTK_SOCKET (icon->priv->socket));
  if (remote_window == NULL)
    {
      g_warning ("cinnamon tray: plug window is gone");
      gdk_error_trap_pop_ignored ();
      return;
    }
  xwindow = GDK_WINDOW_XID (remote_window);
  xdisplay = GDK_WINDOW_XDISPLAY (remote_window);
  screen = gdk_window_get_screen (remote_window);
  xrootwindow = GDK_WINDOW_XID (gdk_screen_get_root_window (screen));
  gdk_window_get_origin (remote_window, &x_root, &y_root);

  /* First make the icon believe the pointer is inside it */
  xcevent.type = EnterNotify;
  xcevent.window = xwindow;
  xcevent.root = xrootwindow;
  xcevent.subwindow = None;
  xcevent.time = clutter_event_get_time (event);
  xcevent.x = gdk_window_get_width (remote_window) / 2;
  xcevent.y = gdk_window_get_height (remote_window) / 2;
  xcevent.x_root = x_root + xcevent.x;
  xcevent.y_root = y_root + xcevent.y;
  xcevent.mode = NotifyNormal;
  xcevent.detail = NotifyNonlinear;
  xcevent.same_screen = True;
  XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent);

  /* Now do the click */
  xbevent.type = ButtonPress;
  xbevent.window = xwindow;
  xbevent.root = xrootwindow;
  xbevent.subwindow = None;
  xbevent.time = xcevent.time;
  xbevent.x = xcevent.x;
  xbevent.y = xcevent.y;
  xbevent.x_root = xcevent.x_root;
  xbevent.y_root = xcevent.y_root;
  xbevent.state = clutter_event_get_state (event);
  xbevent.button = clutter_event_get_button (event);
  xbevent.same_screen = True;
  XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent);

  xbevent.type = ButtonRelease;
  XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent);

  /* And move the pointer back out */
  xcevent.type = LeaveNotify;
  XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent);

  gdk_error_trap_pop_ignored ();
}