Home | History | Annotate | Download | only in message_loop
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/message_loop/message_pump_gtk.h"
      6 
      7 #include <gtk/gtk.h>
      8 #include <gdk/gdkx.h>
      9 
     10 #include "base/debug/trace_event.h"
     11 #include "base/profiler/scoped_profile.h"
     12 
     13 namespace base {
     14 
     15 namespace {
     16 
     17 const char* EventToTypeString(const GdkEvent* event) {
     18   switch (event->type) {
     19     case GDK_NOTHING:           return "GDK_NOTHING";
     20     case GDK_DELETE:            return "GDK_DELETE";
     21     case GDK_DESTROY:           return "GDK_DESTROY";
     22     case GDK_EXPOSE:            return "GDK_EXPOSE";
     23     case GDK_MOTION_NOTIFY:     return "GDK_MOTION_NOTIFY";
     24     case GDK_BUTTON_PRESS:      return "GDK_BUTTON_PRESS";
     25     case GDK_2BUTTON_PRESS:     return "GDK_2BUTTON_PRESS";
     26     case GDK_3BUTTON_PRESS:     return "GDK_3BUTTON_PRESS";
     27     case GDK_BUTTON_RELEASE:    return "GDK_BUTTON_RELEASE";
     28     case GDK_KEY_PRESS:         return "GDK_KEY_PRESS";
     29     case GDK_KEY_RELEASE:       return "GDK_KEY_RELEASE";
     30     case GDK_ENTER_NOTIFY:      return "GDK_ENTER_NOTIFY";
     31     case GDK_LEAVE_NOTIFY:      return "GDK_LEAVE_NOTIFY";
     32     case GDK_FOCUS_CHANGE:      return "GDK_FOCUS_CHANGE";
     33     case GDK_CONFIGURE:         return "GDK_CONFIGURE";
     34     case GDK_MAP:               return "GDK_MAP";
     35     case GDK_UNMAP:             return "GDK_UNMAP";
     36     case GDK_PROPERTY_NOTIFY:   return "GDK_PROPERTY_NOTIFY";
     37     case GDK_SELECTION_CLEAR:   return "GDK_SELECTION_CLEAR";
     38     case GDK_SELECTION_REQUEST: return "GDK_SELECTION_REQUEST";
     39     case GDK_SELECTION_NOTIFY:  return "GDK_SELECTION_NOTIFY";
     40     case GDK_PROXIMITY_IN:      return "GDK_PROXIMITY_IN";
     41     case GDK_PROXIMITY_OUT:     return "GDK_PROXIMITY_OUT";
     42     case GDK_DRAG_ENTER:        return "GDK_DRAG_ENTER";
     43     case GDK_DRAG_LEAVE:        return "GDK_DRAG_LEAVE";
     44     case GDK_DRAG_MOTION:       return "GDK_DRAG_MOTION";
     45     case GDK_DRAG_STATUS:       return "GDK_DRAG_STATUS";
     46     case GDK_DROP_START:        return "GDK_DROP_START";
     47     case GDK_DROP_FINISHED:     return "GDK_DROP_FINISHED";
     48     case GDK_CLIENT_EVENT:      return "GDK_CLIENT_EVENT";
     49     case GDK_VISIBILITY_NOTIFY: return "GDK_VISIBILITY_NOTIFY";
     50     case GDK_NO_EXPOSE:         return "GDK_NO_EXPOSE";
     51     case GDK_SCROLL:            return "GDK_SCROLL";
     52     case GDK_WINDOW_STATE:      return "GDK_WINDOW_STATE";
     53     case GDK_SETTING:           return "GDK_SETTING";
     54     case GDK_OWNER_CHANGE:      return "GDK_OWNER_CHANGE";
     55     case GDK_GRAB_BROKEN:       return "GDK_GRAB_BROKEN";
     56     case GDK_DAMAGE:            return "GDK_DAMAGE";
     57     default:
     58       return "Unknown Gdk Event";
     59   }
     60 }
     61 
     62 }  // namespace
     63 
     64 MessagePumpGtk::MessagePumpGtk() : MessagePumpGlib() {
     65   gdk_event_handler_set(&EventDispatcher, this, NULL);
     66 }
     67 
     68 MessagePumpGtk::~MessagePumpGtk() {
     69   gdk_event_handler_set(reinterpret_cast<GdkEventFunc>(gtk_main_do_event),
     70                         this, NULL);
     71 }
     72 
     73 void MessagePumpGtk::DispatchEvents(GdkEvent* event) {
     74   UNSHIPPED_TRACE_EVENT1("task", "MessagePumpGtk::DispatchEvents",
     75                          "type", EventToTypeString(event));
     76 
     77   WillProcessEvent(event);
     78   gtk_main_do_event(event);
     79   DidProcessEvent(event);
     80 }
     81 
     82 // static
     83 Display* MessagePumpGtk::GetDefaultXDisplay() {
     84   static GdkDisplay* display = gdk_display_get_default();
     85   if (!display) {
     86     // GTK / GDK has not been initialized, which is a decision we wish to
     87     // support, for example for the GPU process.
     88     static Display* xdisplay = XOpenDisplay(NULL);
     89     return xdisplay;
     90   }
     91   return GDK_DISPLAY_XDISPLAY(display);
     92 }
     93 
     94 void MessagePumpGtk::AddObserver(MessagePumpGdkObserver* observer) {
     95   observers_.AddObserver(observer);
     96 }
     97 
     98 void MessagePumpGtk::RemoveObserver(MessagePumpGdkObserver* observer) {
     99   observers_.RemoveObserver(observer);
    100 }
    101 
    102 void MessagePumpGtk::WillProcessEvent(GdkEvent* event) {
    103   FOR_EACH_OBSERVER(MessagePumpGdkObserver,
    104                     observers_,
    105                     WillProcessEvent(event));
    106 }
    107 
    108 void MessagePumpGtk::DidProcessEvent(GdkEvent* event) {
    109   FOR_EACH_OBSERVER(MessagePumpGdkObserver,
    110                     observers_,
    111                     DidProcessEvent(event));
    112 }
    113 
    114 // static
    115 void MessagePumpGtk::EventDispatcher(GdkEvent* event, gpointer data) {
    116   MessagePumpGtk* message_pump = reinterpret_cast<MessagePumpGtk*>(data);
    117   message_pump->DispatchEvents(event);
    118 }
    119 
    120 }  // namespace base
    121