Back to index

lightning-sunbird  0.9+nobinonly
Functions
nsGtkEventHandler.h File Reference
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include "gdksuperwin.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void handle_size_allocate (GtkWidget *w, GtkAllocation *alloc, gpointer p)
gint handle_key_release_event_for_text (GtkObject *w, GdkEventKey *event, gpointer p)
gint handle_key_press_event_for_text (GtkObject *w, GdkEventKey *event, gpointer p)
gint handle_key_release_event (GtkObject *w, GdkEventKey *event, gpointer p)
gint handle_key_press_event (GtkObject *w, GdkEventKey *event, gpointer p)
void handle_xlib_shell_event (GdkSuperWin *superwin, XEvent *event, gpointer p)
void handle_superwin_paint (gint aX, gint aY, gint aWidth, gint aHeight, gpointer aData)
void handle_superwin_flush (gpointer aData)
void handle_gdk_event (GdkEvent *event, gpointer data)

Function Documentation

void handle_gdk_event ( GdkEvent *  event,
gpointer  data 
)

Definition at line 672 of file nsGtkEventHandler.cpp.

{
  GtkObject *eventObject = nsnull;

  // set the last time that we got an event.  we need this for drag
  // and drop if you can believe that.
  guint32 event_time = gdk_event_get_time(event);
  if (event_time)
    nsWidget::SetLastEventTime(event_time);

  // Get the next X event serial ID and save it for later for event
  // processing.  If it stays zero then events won't be processed
  // later.  We're using this as a flag too but with a number this big
  // we're probably not going to overflow and even if we did there
  // wouldn't be any harm.
  unsigned long serial = 0;

  if (XPending(GDK_DISPLAY())) {
    XEvent temp_event;
    XPeekEvent(GDK_DISPLAY(), &temp_event);
    serial = temp_event.xany.serial - 1;
  }

  // try to get the user data for the event window.
  if (event->any.window)
    gdk_window_get_user_data (event->any.window, (void **)&eventObject);

  // If there is an event object and it's a superwin then we need to
  // make sure that the event either is handled locally or is passed
  // on with a legitimate GtkWidget object associated with it so the
  // Gtk mainloop doesn't go spastic.

  if (eventObject && GDK_IS_SUPERWIN(eventObject)) {
    // try to find the nsWindow object associated with this superwin
    nsWindow *window = (nsWindow *)gtk_object_get_data (eventObject,
                                                        "nsWindow");

    // If we don't have a window here anymore, we are probably in
    // the process of being or have been destroyed.  give up now.
    if (!window)
      goto end;

    // Find out if there's a grabbing widget.  If there is and it's a
    // regular gtk widget, and our current event window is not the
    // child of that grab widget, we need to rewrite the event to that
    // gtk grabbing widget.
    PRBool rewriteEvent = PR_FALSE;
    GtkWidget *grabWidget = gtk_grab_get_current();
    GtkWidget *owningWidget = window->GetOwningWidget();

    if (grabWidget &&
        !GTK_IS_MOZAREA(grabWidget) &&
        !gdk_window_child_of_gdk_window(owningWidget->window,
                                        grabWidget->window)) {
      rewriteEvent = PR_TRUE;
    }


    // There are a lot of events that are always dispatched to our
    // internal handler, no matter if there is a grab or not.
    switch(event->type)
      {
      case GDK_NOTHING:
        break;

      case GDK_DESTROY:
      case GDK_DELETE:
      case GDK_PROPERTY_NOTIFY:
      case GDK_EXPOSE:
      case GDK_NO_EXPOSE:
      case GDK_FOCUS_CHANGE:
      case GDK_CONFIGURE:
      case GDK_MAP:
      case GDK_UNMAP:
      case GDK_SELECTION_CLEAR:
      case GDK_SELECTION_REQUEST:
      case GDK_SELECTION_NOTIFY:
      case GDK_CLIENT_EVENT:
      case GDK_VISIBILITY_NOTIFY:
        dispatch_superwin_event(event, window);
        break;

      case GDK_BUTTON_PRESS:
      case GDK_2BUTTON_PRESS:
      case GDK_3BUTTON_PRESS:
      case GDK_KEY_PRESS:
      case GDK_KEY_RELEASE:
        // If we need to rewrite this to the nearest real gtk widget,
        // do it here.
        if (rewriteEvent) {
          gdk_window_unref(event->any.window);
          event->any.window = owningWidget->window;
          gdk_window_ref(event->any.window);
          gtk_main_do_event(event);
          break;
        }

        // Otherwise, just send it to our event handler
        if (GTK_WIDGET_IS_SENSITIVE(owningWidget))
          dispatch_superwin_event(event, window);
        break;

      case GDK_MOTION_NOTIFY:
      case GDK_BUTTON_RELEASE:
      case GDK_PROXIMITY_IN:
      case GDK_PROXIMITY_OUT:
        // See above.
        if (rewriteEvent) {
          gdk_window_unref(event->any.window);
          event->any.window = owningWidget->window;
          gdk_window_ref(event->any.window);
          gtk_propagate_event(grabWidget, event);
          break;
        }

        if (GTK_WIDGET_IS_SENSITIVE(owningWidget))
          dispatch_superwin_event(event, window);
        break;

      case GDK_ENTER_NOTIFY:
      case GDK_LEAVE_NOTIFY:
        // Always dispatch enter and leave notify events to the
        // windows that they happened on so that state can be properly
        // tracked.  The code that handles the enter and leave events
        // tracks sensitivity as well.
        dispatch_superwin_event(event, window);
        break;

      default:
        // XXX lots of DND events not handled?  I don't think that we have to.
        NS_WARNING("Odd, hit default case in handle_gdk_event()\n");
        break;
      }
  }
  else {
    nsWindow  *grabbingWindow = nsWindow::GetGrabWindow();
    
    nsCOMPtr<nsIWidget> grabbingWindowGuard(grabbingWindow);
    GtkWidget *tempWidget = NULL;
    
    if (grabbingWindow) {
      // get the GdkWindow that we are grabbing on
      GdkWindow *grabbingGdkWindow =
        NS_STATIC_CAST(GdkWindow *,
                       grabbingWindow->GetNativeData(NS_NATIVE_WINDOW));
      
      // If the object getting the event in question is a GtkWidget
      // and it's a child of the grabbing window, we need to put a
      // grab on that window before dispatching the event.  We do this
      // so that the gtk mainloop will recognize the widget in
      // question as having the grab.  If we didn't the mainloop
      // wouldn't think that the widget that got the event is the
      // child of the grabbing window, due to the superwin(s) in the
      // middle.
      if (GTK_IS_WIDGET(eventObject)) {
        tempWidget = GTK_WIDGET(eventObject);
        if (gdk_window_child_of_gdk_window(tempWidget->window,
                                           grabbingGdkWindow)) {
          // this is so awesome.  gtk_grab_add/gtk_grab_remove don't
          // have exact push and pop semantics.  if we call grab_add
          // on the object and as part of the dispatching of this
          // event another grab_add is called on it, we can end up
          // releasing the grab early because we always call
          // grab_remove on the object after dispatching the event.
          // we can end up with a widget that doesn't have a grab on
          // it, even though it should.  the scrollbar does this.
          //
          // so, what we do here is to check and see if the widget in
          // question has a parent.  if it does and it's a mozbox
          // object we slam a grab on that instead of the widget
          // itself.  we know that no one is doing grabs on those.
          if (tempWidget->parent) {
            if (GTK_IS_MOZBOX(tempWidget->parent)) {
              tempWidget = tempWidget->parent;
            }
          }
          gtk_grab_add(tempWidget);
        }
        else  {
          // if the gtk widget in question wasn't the child of the
          // grabbing window then the grabbing window gets it.
          dispatch_superwin_event(event, grabbingWindow);
          goto end;
        }
      }
    }

    gtk_main_do_event(event);

    if (tempWidget)
      gtk_grab_remove(tempWidget);

    if (event->type == GDK_BUTTON_RELEASE) {
      // Always clear the button motion target when sending a
      // button release event to a real gtk widget, otherwise
      // mozilla will still think it has the grab.  This happens
      // when there's a native gtk widget popup over a Mozilla
      // area.
      nsWidget::DropMotionTarget();
    }
  }

 end:

  // use the saved serial to process any pending events, now that all
  // the window events have been processed
  if (serial)
    nsAppShell::ProcessBeforeID(serial);

}

Here is the call graph for this function:

Here is the caller graph for this function:

gint handle_key_press_event ( GtkObject *  w,
GdkEventKey *  event,
gpointer  p 
)

Definition at line 537 of file nsGtkEventHandler.cpp.

{
  nsWidget *win = (nsWidget*)p;

  // if there's a focused window rewrite the event to use that window.
  if (nsWidget::sFocusWindow)
    win = nsWidget::sFocusWindow;

  // work around for annoying things.
  if (event->keyval == GDK_Tab)
    if (event->state & GDK_CONTROL_MASK)
      if (event->state & GDK_MOD1_MASK)
        return PR_FALSE;


  NS_ADDREF(win);

  //
  // First, dispatch the Key event as a virtual key down event
  //   but lie about where it came from and say it is from the
  //   window that currently has focus inside our app...
  //
  PRBool noDefault = PR_FALSE;
  nsKeyEvent keyDownEvent(PR_TRUE, NS_KEY_DOWN, win);
  InitKeyEvent(event, keyDownEvent);
  // if we need to suppress this NS_KEY_DOWN event, reset the flag
  if (suppressNextKeyDown == PR_TRUE)
    suppressNextKeyDown = PR_FALSE;
  else
    noDefault = win->OnKey(keyDownEvent);

  // Don't pass Shift, Alt, Control and Meta as NS_KEY_PRESS events.
  if (event->keyval == GDK_Shift_L
      || event->keyval == GDK_Shift_R
      || event->keyval == GDK_Control_L
      || event->keyval == GDK_Control_R
      || event->keyval == GDK_Alt_L
      || event->keyval == GDK_Alt_R
      || event->keyval == GDK_Meta_L
      || event->keyval == GDK_Meta_R)
    return PR_TRUE;

  //
  // Second, dispatch the Key event as a key press event w/ a Unicode
  //  character code.  Note we have to check for modifier keys, since
  // gtk returns a character value for them
  //

  // Call nsConvertCharCodeToUnicode() here to get kevent.charCode 
  nsKeyEvent keyPressEvent(PR_TRUE, NS_KEY_PRESS, win);
  InitKeyPressEvent(event, keyPressEvent);
  if (noDefault) {  // If prevent default set for onkeydown, do the same for onkeypress
    keyPressEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
  }

  if (event->length) {
    if (keyPressEvent.charCode || keyPressEvent.keyCode) {
      // keyPressEvent.charCode or keyPressEvent.keyCode is valid, just 
      // pass to OnKey()
      win->OnKey(keyPressEvent);
    } else if (nsGtkIMEHelper::GetSingleton()) {
      // commit request from IME
      win->IMECommitEvent(event);
    }
  } else { // for Home/End/Up/Down/Left/Right/PageUp/PageDown key
    win->OnKey(keyPressEvent);
  }

  NS_RELEASE(win);

  if (w)
  {
    gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_press_event");
  }

  return PR_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

gint handle_key_press_event_for_text ( GtkObject *  w,
GdkEventKey *  event,
gpointer  p 
)

Definition at line 466 of file nsGtkEventHandler.cpp.

{
  nsTextWidget* win = (nsTextWidget*)p;

  // work around for annoying things.
  if (event->keyval == GDK_Tab)
    if (event->state & GDK_CONTROL_MASK)
      if (event->state & GDK_MOD1_MASK)
        return PR_FALSE;

  NS_ADDREF(win);
  nsKeyEvent keyDownEvent(PR_TRUE, NS_KEY_DOWN, win);
  InitKeyEvent(event, keyDownEvent);
  PRBool noDefault = win->OnKey(keyDownEvent);

  // Don't pass Shift, Control, Alt and Meta as NS_KEY_PRESS events.
  if (event->keyval == GDK_Shift_L
      || event->keyval == GDK_Shift_R
      || event->keyval == GDK_Control_L
      || event->keyval == GDK_Control_R
      || event->keyval == GDK_Alt_L
      || event->keyval == GDK_Alt_R
      || event->keyval == GDK_Meta_L
      || event->keyval == GDK_Meta_R
     )
    return PR_TRUE;

  //
  // Second, dispatch the Key event as a key press event w/ a Unicode
  //  character code.  Note we have to check for modifier keys, since
  // gtk returns a character value for them
  //
  nsKeyEvent keyPressEvent(PR_TRUE, NS_KEY_PRESS, win);
  InitKeyPressEvent(event, keyPressEvent);
  if (noDefault) {  // If prevent default set for onkeydown, do the same for onkeypress
   keyPressEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
  }

  win->OnKey(keyPressEvent);

  NS_RELEASE(win);
  if (w)
  {
    gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_press_event");
  }

  return PR_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

gint handle_key_release_event ( GtkObject *  w,
GdkEventKey *  event,
gpointer  p 
)

Definition at line 616 of file nsGtkEventHandler.cpp.

{
  XEvent nextEvent;
  PRBool    shouldDrop = PR_FALSE;
  // According to the DOM spec if this is the result of a key repeat
  // event we don't let it through since the DOM wants the event
  // stream to look like this: press press press press release.  The
  // way that X does things is to do press release press release, etc.
  // We check to see if this is a key release by checking to see if
  // the next event in the queue is a key press event and it has the
  // exact same timestamp as the current event.

  // have a look in the X queue to see if there's another event in the
  // queue.

  if (XPending(GDK_DISPLAY())) {
    // get a copy of the next event
    XPeekEvent(GDK_DISPLAY(), &nextEvent);
    
    // see if it's a key press event and if it has the same time as
    // the last event.
    if ((nextEvent.xany.type == KeyPress) &&
        (nextEvent.xkey.time == event->time))
    {
      shouldDrop = PR_TRUE;
      // the next key press event shouldn't generate a key down event.
      // this is a global variable
      suppressNextKeyDown = PR_TRUE;
    }
  }

  // should we drop this event?
  if (shouldDrop)
    return PR_TRUE;

  nsWidget *win = (nsWidget *)p;
  if (nsWidget::sFocusWindow)
    win = nsWidget::sFocusWindow;

  nsKeyEvent kevent(PR_TRUE, NS_KEY_UP, win);
  InitKeyEvent(event, kevent);

  NS_ADDREF(win);
  win->OnKey(kevent);
  NS_RELEASE(win);

  if (w)
  {
    gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_release_event");
  }

  return PR_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

gint handle_key_release_event_for_text ( GtkObject *  w,
GdkEventKey *  event,
gpointer  p 
)

Definition at line 517 of file nsGtkEventHandler.cpp.

{
  nsTextWidget* win = (nsTextWidget*)p;
  nsKeyEvent kevent(PR_TRUE, NS_KEY_UP, win);
  InitKeyEvent(event, kevent);
  NS_ADDREF(win);
  win->OnKey(kevent);
  NS_RELEASE(win);
  
  if (w)
  {
    gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_release_event");
  }

  return PR_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void handle_size_allocate ( GtkWidget *  w,
GtkAllocation *  alloc,
gpointer  p 
)

Definition at line 452 of file nsGtkEventHandler.cpp.

{
  nsWindow *widget = (nsWindow *)p;
  nsSizeEvent event(PR_TRUE, NS_SIZE, widget);

  InitAllocationEvent(alloc, event);
  NS_ADDREF(widget);
  widget->OnResize(&event);
  NS_RELEASE(widget);

  delete event.windowSize;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void handle_superwin_flush ( gpointer  aData)

Definition at line 961 of file nsGtkEventHandler.cpp.

{
  nsWindow *window = (nsWindow *)aData;
  window->Update();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void handle_superwin_paint ( gint  aX,
gint  aY,
gint  aWidth,
gint  aHeight,
gpointer  aData 
)

Definition at line 948 of file nsGtkEventHandler.cpp.

{
  nsWindow *window = (nsWindow *)aData;
  nsRect    rect;
  rect.x = aX;
  rect.y = aY;
  rect.width = aWidth;
  rect.height = aHeight;
  window->Invalidate(rect, PR_FALSE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void handle_xlib_shell_event ( GdkSuperWin *  superwin,
XEvent *  event,
gpointer  p 
)

Definition at line 934 of file nsGtkEventHandler.cpp.

{
  nsWindow *window = (nsWindow *)p;
  switch(event->xany.type) {
  case ConfigureNotify:
    window->HandleXlibConfigureNotifyEvent(event);
    break;
  default:
    break;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function: