From: Javier S. Pedro Date: Mon, 29 Mar 2010 19:12:52 +0000 (+0200) Subject: reworked reparents X-Git-Tag: sdlhaa_1_1_0~3 X-Git-Url: https://vcs.maemo.org/git/?p=sdlhildon;a=commitdiff_plain;h=918beb9cc1f0271f6610346f42417cc37b8d6998 reworked reparents --- diff --git a/sdlhaa/debian/changelog b/sdlhaa/debian/changelog index 4133431..92068c2 100644 --- a/sdlhaa/debian/changelog +++ b/sdlhaa/debian/changelog @@ -1,3 +1,11 @@ +sdlhaa (1.1.0) unstable; urgency=low + + * Added new HAA_SetVideoMode call; removed buggy automatic + fullscreen sync. + * Fixed Z Rotation. + + -- Javier S. Pedro Mon, 29 Mar 2010 17:59:06 +0200 + sdlhaa (1.0.0) unstable; urgency=low * Initial Release. diff --git a/sdlhaa/debian/rules b/sdlhaa/debian/rules index d97ef58..976f1ab 100755 --- a/sdlhaa/debian/rules +++ b/sdlhaa/debian/rules @@ -66,7 +66,7 @@ binary-arch: build install dh_strip dh_compress dh_fixperms - dh_makeshlibs -V "libsdl-haa1.2-1 (>= 1.0.0)" + dh_makeshlibs -V "libsdl-haa1.2-1 (>= 1.1.0)" dh_installdeb dh_shlibdeps dh_gencontrol diff --git a/sdlhaa/src/Makefile b/sdlhaa/src/Makefile index 055ac9c..308b76a 100644 --- a/sdlhaa/src/Makefile +++ b/sdlhaa/src/Makefile @@ -4,7 +4,7 @@ CFLAGS:=-g -O0 -Wall -Wextra CC:=gcc RELEASE:=1.2 -VERSION:=0:1:0 +VERSION:=1:2:1 SDL_HAA_TARGET:=libSDL_haa.la diff --git a/sdlhaa/src/SDL_haa.c b/sdlhaa/src/SDL_haa.c index f77510f..3259884 100644 --- a/sdlhaa/src/SDL_haa.c +++ b/sdlhaa/src/SDL_haa.c @@ -52,12 +52,14 @@ typedef struct HAA_ActorPriv { struct HAA_ActorPriv *prev, *next; } HAA_ActorPriv; -static Bool initialized = False; - static Display *display; static Window parent_window; static HAA_ActorPriv *first = NULL, *last = NULL; +/* Queued reparents. */ +static Uint32 queued_reparent_time; +static Bool queued_reparent_fs; + #ifdef HAVE_XSHM static int shm_major, shm_minor; static Bool shm_pixmaps; @@ -77,30 +79,25 @@ int HAA_Init(Uint32 flags) } display = info.info.x11.display; - if (flags & SDL_FULLSCREEN) { - parent_window = info.info.x11.fswindow; - } else { - parent_window = info.info.x11.wmwindow; - } + parent_window = 0; + queued_reparent_time = 0; first = last = NULL; - if (!initialized) { - XInternAtoms(display, (char**)atom_names, ATOM_COUNT, True, atom_values); - initialized = True; + XInternAtoms(display, (char**)atom_names, ATOM_COUNT, True, atom_values); #ifdef HAVE_XSHM - have_shm = XShmQueryVersion(display, &shm_major, &shm_minor, &shm_pixmaps); + have_shm = XShmQueryVersion(display, &shm_major, &shm_minor, &shm_pixmaps); #endif - SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); - } + /* This might add some noise to your event queue, but we need them. */ + SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); return 0; } void HAA_Quit() { - + /* Nothing to do for now */ } static HAA_ActorPriv* find_actor_for_window(Window w) @@ -137,57 +134,120 @@ static void actor_send_message(HAA_ActorPriv* actor, Atom message_type, (XEvent *)&event); } -static void HAA_ReparentAllTo(Window new_parent) +static void reparent_all_to(Window new_parent) { - if (new_parent != parent_window) { - HAA_ActorPriv* a; - /* video mode has changed */ - parent_window = new_parent; - - /* unmap all actors that were already ready */ - for (a = first; a; a = a->next) { - a->parent = parent_window; - if (a->ready) { - XUnmapWindow(display, a->window); - } - } + HAA_ActorPriv* a; + /* video mode has changed */ + parent_window = new_parent; - XSync(display, False); + /* if we don't have any actors, no need to reparent them */ + if (first == NULL) { + assert(last == NULL); + return; + } - /* now remap and reconfigure all actors */ - for (a = first; a; a = a->next) { - if (a->ready) { - XMapWindow(display, a->window); - a->ready = 0; - a->p.pending |= HAA_PENDING_EVERYTHING; - } else { - a->p.pending |= HAA_PENDING_PARENT | HAA_PENDING_SHOW; - } + /* unmap all actors that were already ready */ + for (a = first; a; a = a->next) { + a->parent = parent_window; + if (a->ready) { + XUnmapWindow(display, a->window); } + } + + XSync(display, False); - XFlush(display); + /* now remap and reconfigure all actors */ + for (a = first; a; a = a->next) { + if (a->ready) { + XMapWindow(display, a->window); + a->ready = 0; + a->p.pending |= HAA_PENDING_EVERYTHING; + } else { + a->p.pending |= HAA_PENDING_PARENT | HAA_PENDING_SHOW; + } } + + XFlush(display); } -static void HAA_AutoReparent() +static int auto_reparent_all_to(Bool fullscreen) { SDL_SysWMinfo info; - SDL_Surface *screen = SDL_GetVideoSurface(); Window new_parent; - - if (!screen) return; + XWindowAttributes attr; + Bool is_mapped; + int res; SDL_VERSION(&info.version); - int res = SDL_GetWMInfo(&info); + res = SDL_GetWMInfo(&info); assert(res == 1); - if (screen->flags & SDL_FULLSCREEN) { + /* Delete any pending reparent */ + queued_reparent_time = 0; + + if (fullscreen) { new_parent = info.info.x11.fswindow; } else { new_parent = info.info.x11.wmwindow; } - - HAA_ReparentAllTo(new_parent); + + XGetWindowAttributes(display, new_parent, &attr); + is_mapped = attr.map_state == IsViewable; + + /* Do we really need to reparent? */ + if (new_parent != parent_window) { + /* Yes, we do. */ + if (is_mapped) { + reparent_all_to(new_parent); + return 0; + } else { + return 1; + } + } else if (!is_mapped) { + /* We don't actually need to reparent, + * but we found that our current parent has been unmapped! */ + parent_window = 0; // Make current one it invalid + return 1; // Signal failure + } else { + /* We don't need to reparent and everything is OK. */ + return 0; + } +} + +static void handle_queued_reparent() +{ + if (queued_reparent_time) { + /* A reparent is pending. */ + Uint32 now = SDL_GetTicks(); + if (now > queued_reparent_time) { + /* Try to do the queued reparent now. */ + int res = auto_reparent_all_to(queued_reparent_fs); + if (res != 0) { + /* Failed to reparent? Try again in 200 ms. */ + queued_reparent_time = now + 200; + } + } + } +} + +static void queue_auto_reparent_to(Bool fullscreen, Uint32 delay) +{ + queued_reparent_time = SDL_GetTicks() + delay; + queued_reparent_fs = fullscreen; +} + +int HAA_SetVideoMode() +{ + SDL_Surface *screen = SDL_GetVideoSurface(); + + if (!screen) { + SDL_SetError("Failed to get current video surface"); + return 1; + } + + auto_reparent_all_to(screen->flags & SDL_FULLSCREEN ? True : False); + + return 0; } static void HAA_Pending(HAA_ActorPriv* actor) @@ -225,7 +285,7 @@ static void HAA_Pending(HAA_ActorPriv* actor) actor_send_message(actor, ATOM(_HILDON_ANIMATION_CLIENT_MESSAGE_ROTATION), HAA_Z_AXIS, - actor->p.x_rotation_angle, + actor->p.z_rotation_angle, actor->p.z_rotation_x, actor->p.z_rotation_y, 0); } @@ -249,6 +309,7 @@ static void HAA_Pending(HAA_ActorPriv* actor) actor->p.pending = HAA_PENDING_NOTHING; } +/** Push a SDL_VIDEOEXPOSE event to the queue */ static void sdl_expose() { SDL_Event events[32]; @@ -265,6 +326,7 @@ static void sdl_expose() } } +/** Called when the client ready notification is received. */ static void actor_update_ready(HAA_ActorPriv* actor) { Window window = actor->window; @@ -314,12 +376,11 @@ static void actor_update_ready(HAA_ActorPriv* actor) int HAA_FilterEvent(const SDL_Event *event) { - switch (event->type) { + handle_queued_reparent(); - case SDL_SYSWMEVENT: { + if (event->type == SDL_SYSWMEVENT) { const XEvent *e = &event->syswm.msg->event.xevent; - switch(e->type) { - case PropertyNotify: + if (e->type == PropertyNotify) { if (e->xproperty.atom == ATOM(_HILDON_ANIMATION_CLIENT_READY)) { HAA_ActorPriv* actor = find_actor_for_window(e->xproperty.window); @@ -328,25 +389,37 @@ int HAA_FilterEvent(const SDL_Event *event) return 0; // Handled } } - break; } - } - break; - - case SDL_KEYUP: { - /* For reasons unknown, we seem to receive this on fullscreen events */ - const SDL_keysym *key = &event->key.keysym; - if (key->scancode == 0 && key->sym == SDLK_NUMLOCK && - key->mod == KMOD_NUM) { - /* Either task switched or fullscreen invoked */ - HAA_AutoReparent(); + } else if (event->type == SDL_ACTIVEEVENT) { + /* We know that after an input focus loss, the fullscreen window + * will be unampped. We get no warnings about when this happens. + * So we take a preventive approach and automatically reparent to the + * windowed window when any out of focus event happens. + * Of course, we have then to reparent to the fullscreen window when + * the focus comes back. But we have a problem: there's a 1.5 second + * delay between getting focus and SDL actually mapping the fullscreen + * window, and we cannot reparent back to the fullscreen window while + * it is unmapped. + */ + if (event->active.state == SDL_APPINPUTFOCUS) { + SDL_Surface *screen = SDL_GetVideoSurface(); + if (screen && screen->flags & SDL_FULLSCREEN) { + if (event->active.gain) { + /* Gaining fullscreen focus: + * Wait for 1.5 seconds before reparenting to fullscreen. + */ + queue_auto_reparent_to(True, 1500); + } else { + /* Losing fullscreen focus: + * Windowed mode window is always mapped; can reparent now. + */ + auto_reparent_all_to(False); + } + } } } - break; - - } - return 1; + return 1; // Unhandled event } HAA_Actor* HAA_CreateActor(Uint32 flags, @@ -358,6 +431,13 @@ HAA_Actor* HAA_CreateActor(Uint32 flags, return NULL; } + /* Refresh the parent_window if needed. */ + int res = HAA_SetVideoMode(); + if (res != 0) { + goto cleanup_actor; + return NULL; + } + /* Default actor settings */ actor->p.position_x = 0; actor->p.position_y = 0; @@ -488,13 +568,13 @@ HAA_Actor* HAA_CreateActor(Uint32 flags, goto cleanup_window; } } - + /* Guess alpha mask */ Uint32 Amask = 0; if (image->depth == 32) { Amask = ~(vinfo.red_mask | vinfo.green_mask | vinfo.blue_mask); } - + /* Create GC */ GC gc = actor->gc = XCreateGC(display, window, 0, NULL); XSetForeground(display, gc, 0xFFFFFFFFU); @@ -566,6 +646,7 @@ void HAA_FreeActor(HAA_Actor* a) XFreeColormap(display, actor->colormap); SDL_FreeSurface(actor->p.surface); + /* Remove actor from global linked list */ if (first == actor && last == actor) { assert(!actor->next && !actor->prev); first = NULL; diff --git a/sdlhaa/src/SDL_haa.h b/sdlhaa/src/SDL_haa.h index 6549a20..db9c5d2 100644 --- a/sdlhaa/src/SDL_haa.h +++ b/sdlhaa/src/SDL_haa.h @@ -73,7 +73,7 @@ typedef struct HAA_Actor { } HAA_Actor; /** Invoke after SDL_Init. - @param flags SDL_FULLSCREEN if you will set a fullscreen video mode. + @param flags reserved for future expansion (pass 0) @return 0 if SDL_haa was initialized correctly. */ extern DECLSPEC int SDLCALL HAA_Init(Uint32 flags); @@ -89,6 +89,20 @@ extern DECLSPEC void SDLCALL HAA_Quit(); */ extern DECLSPEC int SDLCALL HAA_FilterEvent(const SDL_Event *event); +/** Call after calling SDL_SetVideoMode() if you have any actors created + * to ensure they're visible in the new window. + * @return 0 if everything went OK. + */ +extern DECLSPEC int SDLCALL HAA_SetVideoMode(void); + +/** Creates both an animation actor and its associated surface. + * @param flags reserved (pass 0) + * @param width size of the actor surface + * @param height + * @param bitsPerPixel depth of the actor surface + * a 32 bpp surface will have an alpha channel. + * @return the created HAA_Actor, or NULL if an error happened. + */ extern DECLSPEC HAA_Actor* SDLCALL HAA_CreateActor(Uint32 flags, int width, int height, int bitsPerPixel); diff --git a/sdlhaa/src/atoms.inc b/sdlhaa/src/atoms.inc index 776c61d..88592b3 100644 --- a/sdlhaa/src/atoms.inc +++ b/sdlhaa/src/atoms.inc @@ -20,13 +20,9 @@ /* Definitions for all the atoms the library is going to use */ enum atoms { - ATOM_HILDON_NON_COMPOSITED_WINDOW = 0, - ATOM_HILDON_STACKABLE_WINDOW, ATOM_NET_WM_STATE, ATOM_NET_WM_STATE_FULLSCREEN, ATOM_NET_WM_WINDOW_TYPE, - ATOM_NET_WM_WINDOW_TYPE_NORMAL, - ATOM_NET_WM_WINDOW_TYPE_DIALOG, ATOM_HILDON_WM_WINDOW_TYPE_ANIMATION_ACTOR, ATOM_HILDON_ANIMATION_CLIENT_READY, ATOM_HILDON_ANIMATION_CLIENT_MESSAGE_SHOW, @@ -39,13 +35,9 @@ enum atoms { }; static const char * atom_names[] = { - "_HILDON_NON_COMPOSITED_WINDOW", - "_HILDON_STACKABLE_WINDOW", "_NET_WM_STATE", "_NET_WM_STATE_FULLSCREEN", "_NET_WM_WINDOW_TYPE", - "_NET_WM_WINDOW_TYPE_NORMAL", - "_NET_WM_WINDOW_TYPE_DIALOG", "_HILDON_WM_WINDOW_TYPE_ANIMATION_ACTOR", "_HILDON_ANIMATION_CLIENT_READY", "_HILDON_ANIMATION_CLIENT_MESSAGE_SHOW",