zoukankan      html  css  js  c++  java
  • GTK/DFB中的WaitCursor

    GTK/DFB中的WaitCursor

    转载时请注明出处和作者联系方式
    作者联系方式:李先静 <xianjimli at hotmail dot com>

    虽然我们实现了单实例应用程序,即在应用程序第二次运行时自动激活第一个实例,并将参数传递给第一个运行实例。但如果在桌面连续点击应用程序的起动图标,会让应用程序起动过过程变得更慢,为了避免这种情况出现,有必要实现类似WaitCursor机制。GTK+-2.6/DFB中没有实现WaitCursor,新版本中好像也没有,只好自己动手了:

    • 在gdkwindow.h文件中增加两个函数:
    gint          gdk_window_begin_wait_cursor(GdkWindow   *window);
    gint          gdk_window_end_wait_cursor(GdkWindow   *window);
    • 在_GdkWindowObject结构中增加waitcursor的信息。
      struct
      {
        gint ref;
        gint elapsed;
        gint timeout_id;
      }wait_cursor;
    • 在gdkwindow-directfb.c中实现这两个函数,很简单,就是实现一个定时器,每隔一段时间更新一下Cursor。
    gint gdk_window_begin_wait_cursor(GdkWindow   *window)
    {
      GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
      g_return_val_if_fail(private != NULL, 0);
    
      private->wait_cursor.ref++;
    
      if(private->wait_cursor.ref == 1 && update_wait_cursor(window))
      {
        private->wait_cursor.elapsed = 0;
        private->wait_cursor.timeout_id = g_timeout_add(250, update_wait_cursor, window);
    #ifndef LINUX_I386  
        gdk_directfb_display->layer->EnableCursor(gdk_directfb_display->layer, 1);
    #endif
      }
    
      return private->wait_cursor.ref;
    }
    
    gint gdk_window_end_wait_cursor(GdkWindow   *window)
    {
      GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
      if(private == NULL || private->wait_cursor.ref <=0)
      {
        return 0;
      }
      private->wait_cursor.ref--;
    #ifndef LINUX_I386  
      gdk_directfb_display->layer->EnableCursor(gdk_directfb_display->layer, private->wait_cursor.ref != 0);
    #endif
    
      return private->wait_cursor.ref;
    }
    
    static gboolean update_wait_cursor(gpointer user_data)
    {
      GdkWindow   *window = user_data;
      GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
      g_return_val_if_fail(private != NULL, FALSE);
    
      int cursor_type = GDK_WAIT_BEGIN +
    (private->wait_cursor.elapsed)%(GDK_WAIT_END - GDK_WAIT_BEGIN + 1);
      GdkCursor* cursor = gdk_cursor_new_for_display (gdk_display_get_default(),
    cursor_type);
      gdk_window_set_cursor(window, cursor);
      gdk_cursor_unref(cursor);
    
      private->wait_cursor.elapsed++;
      if(private->wait_cursor.ref <= 0)
      {
        private->wait_cursor.elapsed = 0;
        private->wait_cursor.timeout_id = 0;
        gdk_window_set_cursor(window, NULL);
      }
    
      return private->wait_cursor.ref > 0;
    }

    在gdkcursor-directfb.c中加载Cursor图片,Cursor图片与主题关联:
    static GdkCursor *
    gdk_cursor_load_wait_cursor(GdkDisplay    *display,
                                GdkCursorType  cursor_type)
    {
      GdkCursor* cursor = NULL;
      if(cursor_type >= GDK_WAIT_BEGIN && cursor_type <= GDK_WAIT_END)
      {
        int index = 0;
        GValue value = {0};
        char* theme = NULL;
        char filename[260] = {0};
        GObject* setting = g_object_get_data (G_OBJECT (gdk_screen_get_default()),
    "gtk-settings");
        g_return_val_if_fail(setting != NULL, NULL);
    
        g_value_init(&value, G_TYPE_STRING);
        g_object_get_property (setting, "gtk-icon-theme-name", &value);
        theme = g_value_get_string(&value);
        index = cursor_type-GDK_WAIT_BEGIN + 1;
        snprintf(filename, sizeof(filename), WAITCURSOR, theme, index);
        if((cursor = gdk_cursor_new_from_name(display, filename)) == NULL)
        {
            snprintf(filename, sizeof(filename), WAITCURSOR, "hicolor", index);
            cursor = gdk_cursor_new_from_name(display, filename);
            g_debug("load %p %s", cursor, filename);
        }
        g_value_reset(&value);
      }
    
      return cursor;
    }
    
    • 要注意的是gdk_cursor_new_from_pixbuf有点问题,pixbuf中的格式居然是GBRA而不是代码中要求的ARGB,要修改一下这个函数,否则无法实现透明效果。

    • 为了避免enable/disable时闪现一下传统的cursor,修改gdk_cursor_new_for_display,让alpha=0,让传统cursor全透明。
    • 出现WaitCursor时,丢弃按键和笔点事件,修改gdk_event_translate:
      if(private->wait_cursor.ref > 0)
      {
        switch (dfbevent->type)
        {
          case DWET_BUTTONDOWN:
          case DWET_BUTTONUP:
          case DWET_MOTION:
          case DWET_KEYDOWN:
          case DWET_KEYUP:
                return NULL;
          default:break;
        }
      }

    在手机上和PC上有点不问,手机上平时不能显示cursor,而且waitcursor的位置要居中,所以还要修改DirectFB:

    • 在dfb_layer_context_create_window中禁止cursor,把以前的dfb_windowstack_cursor_enable(core, stack, true )改为dfb_windowstack_cursor_enable( core, stack, false )
    • 在wm_update_cursor里让位置居中:

    #ifndef LINUX_I386
         if(context->stack->cursor.enabled && (flags & CCUF_POSITION))
         {
              stack->cursor.hot.x = stack->cursor.x - (context->width/2 -
    stack->cursor.size.w);
              stack->cursor.hot.y = stack->cursor.y - (context->height/2 -
    stack->cursor.size.h);
         }
    #endif

    测试了一下,基本功能正常。

    ~~end~~













  • 相关阅读:
    使用Optioanl优雅的处理空值
    综合对比 Kafka、RabbitMQ、RocketMQ、ActiveMQ 四个分布式消息队列
    Nginx 相关介绍
    在Intellij IDEA中使用Debug
    关于Spring的BeanUtils
    MySQL 索引总结
    java中值传递和引用传递
    SQL易错锦集
    Java和SQL取两个字符间的值
    好文章收藏--五分钟理解一致性哈希算法(consistent hashing)
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167633.html
Copyright © 2011-2022 走看看