Package: pterm
Version: 0.58-1

Symptoms:
I start pterm. It brings up its window, which is cleared to black
with the cursor in the top left corner. After this, nothing happens: the
expected shell prompt isn't printed. Pressing keys has no visible effect.
When I click the mouse on the window or use the window manager to switch
away this causes pterm to suddenly update, printing the shell prompt plus
any characters corresponding to keys I had pressed earlier (and if say
I had pressed 'ls<RET>' I also get the ls output now).

Complications:
I only see this on Alpha. I'm using the ratpoison window manager, which
is prone to showing up bugs in applications because it tends to map them
and give them the first Expose event very early.

Interesting things:
If I put a sleep(5) just before the call to gtk_main() at the bottom of
gtkwin.c then the problem goes away: pterm sleeps for five seconds and
then displays the prompt fine.
If I put a call to term_invalidate(inst->term) just before gtk_main()
this also causes the problem to disappear.

---begin true but irrelevant stuff---

I thought that the the problem was that the gtkwin front end quietly
drops any drawing events that occur before we've managed to map the
window, but this doesn't seem to be what's actually happening when
I insert debugging printf()s. Still, maybe the code should be changed?

get_ctx() just returns NULL if inst->area->window is NULL, in which
case the code in terminal.c will do no redrawing (but will clear
its internal flag to say no update is required). This is decidedly
unfortunate because the gtkwin's Expose event handler does a blit
of its internal pixmap onto the window: and the pixmap is blank
because we never drew onto it. (Note the completely bogus comment
in expose_area(), incidentally.) 
Probably the correct approach is to have get_ctx return NULL only
if inst->pixmap is NULL. The code in do_text and do_cursor which
copies from inst->pixmap to inst->window will have to be conditional
on inst->window not being NULL. Dropping drawing events before
inst->pixmap is created will be fine because in configure_area()
where we create the pixmap we subsequently do a term_invalidate().

I also notice that we call gdk_draw_pixmap() for what looks like
a whole screen blit after every call to do_text() or do_cursor().
Wouldn't it be better to just do that once in free_ctx()?

---endit---

Actual problem:
The gtkwin.c timer code implicitly assumes sizeof(int)==sizeof(long).
On alpha, long is 64 bit, so timer ticks as returned by GETTICKCOUNT()
are 64 bits (and at time of writing well overflowing into the high
word). However, we pass this through to the timer_trigger() routine
with GINT_TO_POINTER() and then retrieve it with GPOINTER_TO_INT().
Unfortunately on alpha GPOINTER_TO_INT(x) is defined as
((gint)  (glong) (x)), which truncates the count to 32 bits.
The upshot is that the next timeout is scheduled for aeons in the
future, and we never actually draw anything.

Patch:

---begin---
--- gtkwin.c.orig       2005-10-29 22:58:37.000000000 +0100
+++ gtkwin.c    2005-10-30 00:22:57.000000000 +0100
@@ -1187,14 +1187,14 @@
 
 static gint timer_trigger(gpointer data)
 {
-    long now = GPOINTER_TO_INT(data);
+    long now = (long)(data);
     long next;
     long ticks;
 
     if (run_timers(now, &next)) {
        ticks = next - GETTICKCOUNT();
        timer_id = gtk_timeout_add(ticks > 0 ? ticks : 1, timer_trigger,
-                                  GINT_TO_POINTER(next));
+                                  (gpointer)(next));
     }
 
     /*
@@ -1216,7 +1216,7 @@
        ticks = 1;                     /* just in case */
 
     timer_id = gtk_timeout_add(ticks, timer_trigger,
-                              GINT_TO_POINTER(next));
+                              (gpointer)(next));
 }
 
 void fd_input_func(gpointer data, gint sourcefd, GdkInputCondition condition)
---endit---

Disclaimer: works for me on the Alpha, but totally untested on
32 bit machines. Almost certainly won't work on systems where
pointers are 32 bit but long is 64 bit.

I think that we only ever have one outstanding timer (since
timer_id is a single global, not an array), so we could just
keep 'next' in a global, rather than trying to stuff it into
a pointer and pull it back out again; maybe that'd be cleaner?

Or we could force timer ticks to be 32 bit integers on all
platforms...

-- PMM


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to