Re: Problems Sending Input/Focus to Plug Window



Hi,

I've had a similar problem when trying to give focus to a widget
within the embedded window (from socket application). It seems that
this is not really possible at the present moment. I've created an
example with the plug-socket example code [0]. Here [1] is also a
patch for a gtk_socket_focus_forward () method that could give focus
to the next widget within the embedded window, but I have not yet
received any response on this approach. An example of how this could
be used (using the plug-socket example) can also be found in the
focus_forward branch [2].

The bug report has some more information, also I sent an email to this
list a while ago:
https://mail.gnome.org/archives/gtk-app-devel-list/2014-May/msg00002.html

[0] https://github.com/gauteh/plug-socket-grab-focus
[1] https://bugzilla.gnome.org/show_bug.cgi?id=729248
[2] https://github.com/gauteh/plug-socket-grab-focus/tree/focus_forward

Cheers, Gaute

On Tue, Aug 26, 2014 at 10:24 PM, Benjamin Schnitzler
<benjaminschnitzler googlemail com> wrote:
Dear list members,

I'm trying to create an unmanaged Gtk window containing one or more embedded
windows (for example terminals). I'm having Problems focussing and sending input
to these embedded windows. I already tried to embed an xterm and a urxvt window.
At least the urxvt works correctly, if no other elements are in the window.
However putting a button into the window leads to the terminal loosing its focus
with no apparent way to let it regain it. It is however possible to send an
XEMBED_FOCUS_IN message to the urxvt window. Whe the urxvt recieves the message,
it will at least change the cursor correctly, but yet, no input is send to it.
Using an xterm doesn't work, even with normal toplevel windows. Can You help me
in solving this problem? Here is a gist containing a more or less minimal
example (I'm using the gtkmm C++ interface):
https://gist.github.com/anonymous/f179ff891f7c8029faf8
or clone it via:
git clone https://gist.github.com/f179ff891f7c8029faf8.git

  Benjamin

For reference, here is the code from the gist:

Makefile:
sockfoc: sockfoc.cc window_ext.h
  g++ -ggdb sockfoc.cc -o sockfoc `pkg-config gtkmm-3.0 --cflags --libs` -lX11

sockfoc.cc
#include <gtkmm.h>
#include <gtkmm/socket.h>

#include "window_ext.h"

#define XEMBED_FOCUS_IN 4
#define XEMBED_FOCUS_CURRENT 0

class TheWindow : public WindowExt
{
  Gtk::Box* box;
  Gtk::Socket* socket;
  Gtk::Button* button_close;

  public:
    TheWindow() : WindowExt(Gtk::WINDOW_POPUP)
    {
      signal_realize().connect( sigc::mem_fun(*this,&TheWindow::add_term) );

      button_close = Gtk::manage( new Gtk::Button("Close Window.") );
      box = Gtk::manage( new Gtk::Box(Gtk::ORIENTATION_VERTICAL) );
      box->pack_start( *button_close );
      add(*box);

      button_close->signal_clicked().connect(
        sigc::mem_fun(*this,&Window::hide)
      );

      show_all();
      grab_keyboard(this->get_window());
    }

    void add_term()
    {
      socket = Gtk::manage( new Gtk::Socket );
      box->pack_start( *socket );
      int xid = socket->get_id();
      char buffer[50];
      //sprintf(buffer, "xterm -into %d &", xid);
      sprintf(buffer, "urxvt -embed %d &", xid);
      system(buffer);
      box->show_all();

      socket->signal_plug_added().connect(
          sigc::mem_fun(*this, &TheWindow::send_focus_in)
      );

      socket->signal_plug_removed().connect(
          sigc::mem_fun(*this, &TheWindow::on_plug_removed)
      );

    }

    bool on_plug_removed()
    {
      hide();
      return false;
    }

    void send_focus_in()
    {
      GdkWindow* plug = socket->get_plug_window()->gobj();
      GdkDisplay *display = gdk_window_get_display(plug);

      XClientMessageEvent xclient;
      memset(&xclient, 0, sizeof (xclient));

      xclient.window = GDK_WINDOW_XID(plug);
      xclient.type = ClientMessage;
      xclient.message_type =
          gdk_x11_get_xatom_by_name_for_display(display, "_XEMBED");
      xclient.format = 32;
      xclient.data.l[0] = gtk_get_current_event_time();
      xclient.data.l[1] = XEMBED_FOCUS_IN;
      xclient.data.l[2] = XEMBED_FOCUS_CURRENT;
      xclient.data.l[3] = 0;
      xclient.data.l[4] = 0;

      XSendEvent(
          GDK_WINDOW_XDISPLAY(plug),
          GDK_WINDOW_XID(plug), False, NoEventMask, (XEvent *)&xclient
      );
    }
};

int main(int argc, char** argv)
{
  Glib::RefPtr<Gtk::Application> app;
  app = Gtk::Application::create(argc, argv, "socket.focustest");

  TheWindow win;
  return app->run(win);
}

window_ext.h:
#ifndef WINDOW_EXT_H
#define WINDOW_EXT_H

#include <gtkmm.h>
#include <iostream>

class Overlay;

class WindowExt : public Gtk::Window
{
  private:
    Cairo::RefPtr<Cairo::Region> shape;

  public:
    void grab_keyboard(Glib::RefPtr<Gdk::Window> dest)
    {
      Glib::RefPtr<Gdk::Display> display = get_display();
      Glib::RefPtr<Gdk::DeviceManager> deviceM = display->get_device_manager();

      std::vector< Glib::RefPtr<Gdk::Device> >devices =
        deviceM->list_devices( Gdk::DEVICE_TYPE_MASTER );

      std::vector< Glib::RefPtr<Gdk::Device> >::iterator it;

      for(it = devices.begin(); it != devices.end(); ++it)
      {
        for(int grab = Gdk::GRAB_NOT_VIEWABLE; grab == Gdk::GRAB_NOT_VIEWABLE;)
        {
          grab = (*it)->grab(
            dest, Gdk::OWNERSHIP_NONE, true,
            Gdk::ALL_EVENTS_MASK, GDK_CURRENT_TIME
          );
        }
      }
    }

    WindowExt(Gtk::WindowType type=Gtk::WINDOW_TOPLEVEL) : Window(type) {}

    virtual ~WindowExt(){}
};

#endif
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list gnome org
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]