2007-04-25 Emmanuele Bassi <ebassi@openedhand.com>
authorEmmanuele Bassi <ebassi@openedhand.com>
Wed, 25 Apr 2007 14:22:24 +0000 (14:22 +0000)
committerEmmanuele Bassi <ebassi@openedhand.com>
Wed, 25 Apr 2007 14:22:24 +0000 (14:22 +0000)
Merge from clutter.git/master

* clutter/glx/clutter-event-glx.c:
* clutter/glx/clutter-stage-glx.c: Implement the _NET_WM_PING
protocol handling on the main stage window.

* clutter/clutter-stage.h:
* clutter/clutter-stage.c:
* clutter/clutter-main.c: Handle CLUTTER_DELETE events internally,
by calling clutter_main_quit(), and remove the ::delete-event
signal from ClutterStage; clean up the signal emission sequence
for the events: emit the ::event signal before emitting any signal
and the ::event-after signal after the signal has been emitted; move
the signal emission calls inside ClutterStage so we can call
g_signal_emit() instead of g_signal_emit_by_name(), thus sparing us
a lookup for each event.

* examples/test.c: Remove ::delete-event signal handling.

ChangeLog
clutter/clutter-main.c
clutter/clutter-stage.c
clutter/clutter-stage.h
clutter/egl/clutter-stage-egl.c
clutter/glx/clutter-event-glx.c
clutter/glx/clutter-stage-glx.c
doc/reference/clutter-sections.txt
doc/reference/tmpl/clutter-stage.sgml
examples/test.c

index 86a5cd7..21c49ba 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2007-04-25  Emmanuele Bassi  <ebassi@openedhand.com>
+
+       Merge from clutter.git/master
+
+       * clutter/glx/clutter-event-glx.c:
+       * clutter/glx/clutter-stage-glx.c: Implement the _NET_WM_PING
+       protocol handling on the main stage window.
+
+       * clutter/clutter-stage.h:
+       * clutter/clutter-stage.c:
+       * clutter/clutter-main.c: Handle CLUTTER_DELETE events internally,
+       by calling clutter_main_quit(), and remove the ::delete-event
+       signal from ClutterStage; clean up the signal emission sequence
+       for the events: emit the ::event signal before emitting any signal
+       and the ::event-after signal after the signal has been emitted; move
+       the signal emission calls inside ClutterStage so we can call
+       g_signal_emit() instead of g_signal_emit_by_name(), thus sparing us
+       a lookup for each event.
+
+       * examples/test.c: Remove ::delete-event signal handling.
+
 2007-04-19  Emmanuele Bassi  <ebassi@openedhand.com>
 
        Merge from clutter.git/master
index 41977cc..74b18b8 100644 (file)
@@ -128,50 +128,30 @@ clutter_main_do_event (ClutterEvent *event,
   stage = _clutter_backend_get_stage (backend);
   if (!stage)
     return;
-  
+
   switch (event->type)
     {
     case CLUTTER_NOTHING:
       break;
+
+    case CLUTTER_DESTROY_NOTIFY:
+    case CLUTTER_DELETE:
+      if (clutter_stage_event (CLUTTER_STAGE (stage), event))
+        clutter_main_quit ();
+      break;
+    
+    case CLUTTER_KEY_PRESS:
+    case CLUTTER_KEY_RELEASE:
+    case CLUTTER_MOTION:
     case CLUTTER_BUTTON_PRESS:
     case CLUTTER_2BUTTON_PRESS:
     case CLUTTER_3BUTTON_PRESS:
-      g_signal_emit_by_name (stage, "button-press-event", event);
-      break;
     case CLUTTER_BUTTON_RELEASE:
-      g_signal_emit_by_name (stage, "button-release-event", event);
-      break;
     case CLUTTER_SCROLL:
-      g_signal_emit_by_name (stage, "scroll-event", event);
-      break;
-    case CLUTTER_KEY_PRESS:
-      g_signal_emit_by_name (stage, "key-press-event", event);
-      break;
-    case CLUTTER_KEY_RELEASE:
-      g_signal_emit_by_name (stage, "key-release-event", event);
-      break;
-    case CLUTTER_MOTION:
-      g_signal_emit_by_name (stage, "motion-event", event);
-      break;
-    case CLUTTER_DELETE:
-      {
-        gboolean res = FALSE;
-
-        g_object_ref (stage);
-
-        g_signal_emit_by_name (stage, "delete-event", event, &res);
-        CLUTTER_NOTE (EVENT, "delete-event return: %s",
-                      res == TRUE ? "true" : "false");
-        if (!res)
-          clutter_main_quit ();
-        
-        g_object_unref (stage);
-      }
+      clutter_stage_event (CLUTTER_STAGE (stage), event);
       break;
+
     case CLUTTER_STAGE_STATE:
-      break;
-    case CLUTTER_DESTROY_NOTIFY:
-      break;
     case CLUTTER_CLIENT_MESSAGE:
       break;
     }
@@ -189,7 +169,8 @@ clutter_main_quit (void)
 
   g_return_if_fail (context->main_loops != NULL);
 
-  g_main_loop_quit (context->main_loops->data);
+  if (g_main_loop_is_running (context->main_loops->data))
+    g_main_loop_quit (context->main_loops->data);
 }
 
 /**
@@ -232,6 +213,7 @@ clutter_main (void)
 
   if (g_main_loop_is_running (context->main_loops->data))
     {
+      /* FIXME - add thread locking around this call */
       g_main_loop_run (loop);
     }
 
@@ -257,7 +239,7 @@ clutter_main (void)
  * Locks the Clutter thread lock.
  */
 void
-clutter_threads_enter(void)
+clutter_threads_enter (void)
 {
   ClutterMainContext *context = CLUTTER_CONTEXT ();
   
index 59dcb2b..47d8e69 100644 (file)
@@ -78,6 +78,7 @@ enum
 enum
 {
   EVENT,
+  EVENT_AFTER,
   BUTTON_PRESS_EVENT,
   BUTTON_RELEASE_EVENT,
   SCROLL_EVENT,
@@ -85,12 +86,11 @@ enum
   KEY_RELEASE_EVENT,
   MOTION_EVENT,
   STAGE_STATE_EVENT,
-  DELETE_EVENT,
   
   LAST_SIGNAL
 };
 
-static guint stage_signals[LAST_SIGNAL] = { 0 };
+static guint stage_signals[LAST_SIGNAL] = { 0, };
 
 static void
 clutter_stage_paint (ClutterActor *actor)
@@ -249,6 +249,23 @@ clutter_stage_class_init (ClutterStageClass *klass)
                  G_TYPE_NONE, 1,
                  CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
   /**
+   * ClutterStage::event-after:
+   * @stage: the actor which received the event
+   * @event: a #ClutterEvent
+   *
+   * The ::event-after signal is emitted after each event, except for
+   * the "delete-event" is received by @stage.
+   */
+  stage_signals[EVENT_AFTER] =
+    g_signal_new ("event-after",
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ClutterStageClass, event_after),
+                  NULL, NULL,
+                  clutter_marshal_VOID__BOXED,
+                  G_TYPE_NONE, 1,
+                  CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+  /**
    * ClutterStage::button-press-event:
    * @stage: the actor which received the event
    * @event: a #ClutterButtonEvent
@@ -353,16 +370,6 @@ clutter_stage_class_init (ClutterStageClass *klass)
                  G_TYPE_NONE, 1,
                  CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
   
-  stage_signals[DELETE_EVENT] =
-    g_signal_new ("delete-event",
-                  G_TYPE_FROM_CLASS (gobject_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (ClutterStageClass, delete_event),
-                  _clutter_boolean_accumulator, NULL,
-                  clutter_marshal_BOOLEAN__BOXED,
-                  G_TYPE_BOOLEAN, 1,
-                  CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
-  
   g_type_class_add_private (gobject_class, sizeof (ClutterStagePrivate));
 }
 
@@ -836,6 +843,83 @@ clutter_stage_get_actor_at_pos (ClutterStage *stage,
   return found;
 }
 
+/**
+ * clutter_stage_event:
+ * @stage: a #ClutterStage
+ * @event: a #ClutterEvent
+ *
+ * This function is used to emit an event on the main stage.
+ * You should rarely need to use this function, except for
+ * synthetising events.
+ *
+ * Return value: the return value from the signal emission
+ *
+ * Since: 0.4
+ */
+gboolean
+clutter_stage_event (ClutterStage *stage,
+                     ClutterEvent *event)
+{
+  gboolean res = TRUE;
+  gint signal_num = -1;
+
+  g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  g_object_ref (stage);
+
+  g_signal_emit (stage, stage_signals[EVENT], 0, event);
+  
+  switch (event->type)
+    {
+    case CLUTTER_NOTHING:
+      break;
+    case CLUTTER_BUTTON_PRESS:
+    case CLUTTER_2BUTTON_PRESS:
+    case CLUTTER_3BUTTON_PRESS:
+      signal_num = BUTTON_PRESS_EVENT;
+      break;
+    case CLUTTER_BUTTON_RELEASE:
+      signal_num = BUTTON_RELEASE_EVENT;
+      break;
+    case CLUTTER_SCROLL:
+      signal_num = SCROLL_EVENT;
+      break;
+    case CLUTTER_KEY_PRESS:
+      signal_num = KEY_PRESS_EVENT;
+      break;
+    case CLUTTER_KEY_RELEASE:
+      signal_num = KEY_RELEASE_EVENT;
+      break;
+    case CLUTTER_MOTION:
+      signal_num = MOTION_EVENT;
+      break;
+    case CLUTTER_DELETE:
+      signal_num = -1;
+      break;
+    case CLUTTER_STAGE_STATE:
+      signal_num = -1;
+      break;
+    case CLUTTER_DESTROY_NOTIFY:
+      signal_num = -1;
+      break;
+    case CLUTTER_CLIENT_MESSAGE:
+      signal_num = -1;
+      break;
+    }
+
+  if (signal_num != -1)
+    {
+      g_signal_emit (stage, stage_signals[signal_num], 0, event);
+      g_signal_emit (stage, stage_signals[EVENT_AFTER], 0, event);
+      res = TRUE;
+    }
+
+  g_object_unref (stage);
+
+  return res;
+}
+
 /*** Perspective boxed type ******/
 
 /**
index b269293..ac4d605 100644 (file)
@@ -94,6 +94,8 @@ struct _ClutterStageClass
   /* signals */
   void     (* event)                (ClutterStage           *stage,
                                      ClutterEvent           *event);
+  void     (* event_after)          (ClutterStage           *stage,
+                                     ClutterEvent           *event);
   void     (* button_press_event)   (ClutterStage           *stage,
                                     ClutterButtonEvent     *event);
   void     (* button_release_event) (ClutterStage           *stage,
@@ -108,8 +110,6 @@ struct _ClutterStageClass
                                      ClutterMotionEvent     *event);
   void     (* stage_state_event)    (ClutterStage           *stage,
                                      ClutterStageStateEvent *event);
-  gboolean (* delete_event)         (ClutterStage           *stage,
-                                     ClutterAnyEvent        *event);
 
   /* padding for future expansion */
   void (*_clutter_stage1) (void);
@@ -158,6 +158,8 @@ GdkPixbuf *   clutter_stage_snapshot         (ClutterStage       *stage,
                                               gint                y,
                                               gint                width,
                                               gint                height);
+gboolean      clutter_stage_event            (ClutterStage       *stage,
+                                              ClutterEvent       *event);
 
 G_END_DECLS
 
index f6bb7f3..c339bec 100644 (file)
@@ -206,10 +206,8 @@ clutter_stage_egl_paint (ClutterActor *self)
   glDisable (GL_LIGHTING); 
   glDisable (GL_DEPTH_TEST);
 
-  /* FIXME Check is redundant */
-  if (G_LIKELY(CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->paint))
-    /* Basically call up to ClutterGroup paint here */
-    CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->paint (self);
+  /* Basically call up to ClutterGroup paint here */
+  CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->paint (self);
 
   /* Why this paint is done in backend as likely GL windowing system
    * specific calls, like swapping buffers.
@@ -370,7 +368,8 @@ static void
 clutter_stage_egl_set_offscreen (ClutterStage *stage,
                                  gboolean      offscreen)
 {
-
+  g_warning ("Stage of type `%s' do not support ClutterStage::set_offscreen",
+             G_OBJECT_TYPE_NAME (stage));
 }
 
 static void
@@ -388,7 +387,8 @@ clutter_stage_egl_draw_to_pixbuf (ClutterStage *stage,
                                   gint          width,
                                   gint          height)
 {
-  /* FIXME: implement */
+  g_warning ("Stage of type `%s' do not support ClutterStage::draw_to_pixbuf",
+             G_OBJECT_TYPE_NAME (stage));
 }
 
 static void
@@ -474,6 +474,15 @@ clutter_egl_get_stage_visual (ClutterStage *stage)
   return CLUTTER_STAGE_EGL (stage)->xvisinfo;
 }
 
+/**
+ * clutter_egl_set_stage_foreign:
+ * @stage: a #ClutterStage
+ * @window: FIXME
+ *
+ * FIXME
+ *
+ * Since: 0.4
+ */
 void
 clutter_egl_set_stage_foreign (ClutterStage *stage,
                                Window        window)
index 59ef931..fd3d9ba 100644 (file)
@@ -290,6 +290,7 @@ handle_wm_protocols_event (ClutterBackendGlx *backend_glx,
 {
   Atom atom = (Atom) xevent->xclient.data.l[0];
   Atom Atom_WM_DELETE_WINDOW;
+  Atom Atom_NEW_WM_PING;
 
   ClutterStage *stage = CLUTTER_STAGE (backend_glx->stage);
   Window stage_xwindow = clutter_glx_get_stage_window (stage);
@@ -297,6 +298,7 @@ handle_wm_protocols_event (ClutterBackendGlx *backend_glx,
   Atom_WM_DELETE_WINDOW = XInternAtom (backend_glx->xdpy,
                                        "WM_DELETE_WINDOW",
                                         False);
+  Atom_NEW_WM_PING = XInternAtom (backend_glx->xdpy, "_NET_WM_PING", False);
 
   if (atom == Atom_WM_DELETE_WINDOW &&
       xevent->xany.window == stage_xwindow)
@@ -315,8 +317,21 @@ handle_wm_protocols_event (ClutterBackendGlx *backend_glx,
 
       return TRUE;
     }
+  else if (atom == Atom_NEW_WM_PING &&
+           xevent->xany.window == stage_xwindow)
+    {
+      XClientMessageEvent xclient = xevent->xclient;
+
+      xclient.window = backend_glx->xwin_root;
+      XSendEvent (backend_glx->xdpy, xclient.window,
+                  False,
+                  SubstructureRedirectMask | SubstructureNotifyMask,
+                  (XEvent *) &xclient);
+
+      return FALSE;
+    }
 
-  /* do not send the WM_PROTOCOLS events to the queue */
+  /* do not send any of the WM_PROTOCOLS events to the queue */
   return FALSE;
 }
 
index c5109c4..2141517 100644 (file)
@@ -112,11 +112,10 @@ static void
 set_wm_protocols (Display *xdisplay,
                   Window   xwindow)
 {
-  Atom protocols[3];
+  Atom protocols[2];
   int n = 0;
   
   protocols[n++] = XInternAtom (xdisplay, "WM_DELETE_WINDOW", False);
-  protocols[n++] = XInternAtom (xdisplay, "WM_TAKE_FOCUS", False);
   protocols[n++] = XInternAtom (xdisplay, "_NET_WM_PING", False);
 
   XSetWMProtocols (xdisplay, xwindow, protocols, n);
index efc6e9c..2757674 100644 (file)
@@ -331,6 +331,7 @@ clutter_stage_show_cursor
 clutter_stage_hide_cursor
 clutter_stage_get_actor_at_pos
 clutter_stage_snapshot
+clutter_stage_event
 <SUBSECTION Standard>
 CLUTTER_STAGE
 CLUTTER_IS_STAGE
index 788b4f6..03abded 100644 (file)
@@ -80,16 +80,15 @@ Macro evaluating to the height of the #ClutterStage
 @clutterstage: the object which received the signal.
 @arg1: 
 
-<!-- ##### SIGNAL ClutterStage::delete-event ##### -->
+<!-- ##### SIGNAL ClutterStage::event ##### -->
 <para>
 
 </para>
 
 @clutterstage: the object which received the signal.
-@Param2: 
-@Returns: 
+@arg1: 
 
-<!-- ##### SIGNAL ClutterStage::event ##### -->
+<!-- ##### SIGNAL ClutterStage::event-after ##### -->
 <para>
 
 </para>
@@ -160,6 +159,7 @@ Macro evaluating to the height of the #ClutterStage
 @set_offscreen: 
 @draw_to_pixbuf: 
 @event: 
+@event_after: 
 @button_press_event: 
 @button_release_event: 
 @scroll_event: 
@@ -167,7 +167,6 @@ Macro evaluating to the height of the #ClutterStage
 @key_release_event: 
 @motion_event: 
 @stage_state_event: 
-@delete_event: 
 @_clutter_stage1: 
 @_clutter_stage2: 
 @_clutter_stage3: 
@@ -257,3 +256,13 @@ Macro evaluating to the height of the #ClutterStage
 @Returns: 
 
 
+<!-- ##### FUNCTION clutter_stage_event ##### -->
+<para>
+
+</para>
+
+@stage: 
+@event: 
+@Returns: 
+
+
index 3cfdf68..c4874e8 100644 (file)
@@ -79,22 +79,6 @@ key_release_cb (ClutterStage    *stage,
   g_print ("key-release-event\n");
 }
 
-static gboolean
-delete_event_cb (ClutterStage *stage,
-                 ClutterEvent *event,
-                 gpointer      data)
-{
-  static gboolean res = FALSE;
-
-  g_print ("delete-event: %s\n",
-           res == FALSE ? "first attempt" : "second attempt");
-
-  res = !res;
-
-  return res;
-}
-
-
 int
 main (int argc, char *argv[])
 {
@@ -107,8 +91,6 @@ main (int argc, char *argv[])
   clutter_init (&argc, &argv);
 
   stage = clutter_stage_get_default ();
-  g_signal_connect (stage, "delete-event",
-                    G_CALLBACK (delete_event_cb), NULL);
   g_signal_connect (stage, "key-press-event",
                     G_CALLBACK (key_press_cb), NULL);
   g_signal_connect (stage, "key-release-event",