From a7a511ce79e74a38bbfd3d83bc6df1526440ca6e Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 25 Apr 2007 14:22:24 +0000 Subject: [PATCH] 2007-04-25 Emmanuele Bassi 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 | 21 +++++ clutter/clutter-main.c | 50 ++++-------- clutter/clutter-stage.c | 108 +++++++++++++++++++++++--- clutter/clutter-stage.h | 6 +- clutter/egl/clutter-stage-egl.c | 21 +++-- clutter/glx/clutter-event-glx.c | 17 +++- clutter/glx/clutter-stage-glx.c | 3 +- doc/reference/clutter-sections.txt | 1 + doc/reference/tmpl/clutter-stage.sgml | 19 +++-- examples/test.c | 18 ----- 10 files changed, 184 insertions(+), 80 deletions(-) diff --git a/ChangeLog b/ChangeLog index 86a5cd7e6..21c49ba11 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2007-04-25 Emmanuele Bassi + + 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 Merge from clutter.git/master diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 41977cc30..74b18b81a 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -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); + clutter_stage_event (CLUTTER_STAGE (stage), 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); - } - 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 (); diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 59dcb2b0f..47d8e69ea 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -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) @@ -248,6 +248,23 @@ clutter_stage_class_init (ClutterStageClass *klass) clutter_marshal_VOID__BOXED, 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 @@ -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 ******/ /** diff --git a/clutter/clutter-stage.h b/clutter/clutter-stage.h index b269293c4..ac4d605f8 100644 --- a/clutter/clutter-stage.h +++ b/clutter/clutter-stage.h @@ -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 diff --git a/clutter/egl/clutter-stage-egl.c b/clutter/egl/clutter-stage-egl.c index f6bb7f395..c339bec98 100644 --- a/clutter/egl/clutter-stage-egl.c +++ b/clutter/egl/clutter-stage-egl.c @@ -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) diff --git a/clutter/glx/clutter-event-glx.c b/clutter/glx/clutter-event-glx.c index 59ef931fb..fd3d9ba48 100644 --- a/clutter/glx/clutter-event-glx.c +++ b/clutter/glx/clutter-event-glx.c @@ -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; - /* do not send the WM_PROTOCOLS events to the queue */ + xclient.window = backend_glx->xwin_root; + XSendEvent (backend_glx->xdpy, xclient.window, + False, + SubstructureRedirectMask | SubstructureNotifyMask, + (XEvent *) &xclient); + + return FALSE; + } + + /* do not send any of the WM_PROTOCOLS events to the queue */ return FALSE; } diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c index c5109c4d9..2141517ad 100644 --- a/clutter/glx/clutter-stage-glx.c +++ b/clutter/glx/clutter-stage-glx.c @@ -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); diff --git a/doc/reference/clutter-sections.txt b/doc/reference/clutter-sections.txt index efc6e9c7b..275767479 100644 --- a/doc/reference/clutter-sections.txt +++ b/doc/reference/clutter-sections.txt @@ -331,6 +331,7 @@ clutter_stage_show_cursor clutter_stage_hide_cursor clutter_stage_get_actor_at_pos clutter_stage_snapshot +clutter_stage_event CLUTTER_STAGE CLUTTER_IS_STAGE diff --git a/doc/reference/tmpl/clutter-stage.sgml b/doc/reference/tmpl/clutter-stage.sgml index 788b4f6c2..03abded50 100644 --- a/doc/reference/tmpl/clutter-stage.sgml +++ b/doc/reference/tmpl/clutter-stage.sgml @@ -80,16 +80,15 @@ Macro evaluating to the height of the #ClutterStage @clutterstage: the object which received the signal. @arg1: - + @clutterstage: the object which received the signal. -@Param2: -@Returns: +@arg1: - + @@ -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: + + + + + +@stage: +@event: +@Returns: + + diff --git a/examples/test.c b/examples/test.c index 3cfdf68b8..c4874e8ba 100644 --- a/examples/test.c +++ b/examples/test.c @@ -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",