dm.c

Go to the documentation of this file.
00001 /*
00002  * File Name: display.c
00003  */
00004 
00005 /*
00006  * This file is part of sysd.
00007  *
00008  * sysd is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * sysd is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2008 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 //----------------------------------------------------------------------------
00028 // Include Files
00029 //----------------------------------------------------------------------------
00030 
00031 #include "config.h"
00032 
00033 // system include files, between < >
00034 #include <glib.h>
00035 //#include <gtk/gtk.h>
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <fcntl.h>
00039 #include <sys/ioctl.h>
00040 #include <sys/time.h>
00041 #include <arpa/inet.h>
00042 #include <string.h>
00043 
00044 // ereader include files, between < >
00045 #include <liberipc/eripc.h>
00046 #include <liberipc/eripc_support.h>
00047 #include <liberutils/display_utils.h>
00048 
00049 // local include files, between " "
00050 #include "log.h"
00051 #include "delta.h"
00052 #include "system.h"
00053 #include "tasks.h"
00054 #include "xwindow.h"
00055 #include "ipc.h"
00056 
00057 #define UNUSED(x) (void)(x)
00058 
00059 
00060 //----------------------------------------------------------------------------
00061 // Type Declarations
00062 //----------------------------------------------------------------------------
00063 
00064 // TCP port for incoming GTK messages
00065 #define DMPORT          50555
00066 #define LOCALHOST       0x7f000001L // "127.0.0.1"
00067 
00068 #define DM_MAXCHARONLINE 1024
00069 #define DM_CMD_NAME       128
00070 #define DM_ARGLENGTH      256
00071 #define DM_N_ARG           16
00072 
00073 // TCP port for incoming WM messages
00074 //#define WMPORT          50556
00075 //#define WM_NAME            64
00076 
00077 #define WAVEFORM_QUICK          6 // WAVEFORM_1BPP_IMAGE
00078 #define WAVEFORM_PARTIAL        9 // WAVEFORM_2BPP_IMAGE
00079 #define WAVEFORM_FULL           1 // WAVEFORM_4BPP_IMAGE
00080 
00081 // Times [ms] needed for the waveform playback during which delta is unavailable 
00082 #define DELTA_TIME_FULL         900*1000 
00083 // NOTE: not actual delay but this makes the soft keyboard act better
00084 #define DELTA_TIME_QUICK        50*1000                 
00085 
00086 typedef enum
00087 {
00088     DM_INFO,      // automically by GTK
00089     DM_FORCE,     // forced by application
00090     DM_UNDEFINED
00091 } DMCommandCode;
00092 
00093 typedef struct
00094 {
00095     int  pid;
00096     int  x, y;
00097     int  w, h;
00098     int  shouldIgnore;
00099     int  isWindow;
00100     int  windowType;
00101     char widgetType[64];
00102     int  isFocus;
00103 } DMCommandInfo;
00104 
00105 typedef struct
00106 {
00107     int  pid;
00108     int  takeControl;
00109     int  hint;
00110 } DMCommandForce;
00111 
00112 typedef struct
00113 {
00114     DMCommandCode cmd;
00115     DMCommandInfo info;
00116     DMCommandForce force;
00117 } DMCommand;
00118 
00119 typedef struct
00120 {
00121     char    name[DM_CMD_NAME]; // Command Name
00122     int     cc;             // Command Code
00123     char    arg[DM_N_ARG][DM_ARGLENGTH];
00124     int     nArg;
00125 } erDmCmd_t;
00126 
00127 
00128 
00129 typedef struct display_update_info DisplayUpdateInfo;
00130 typedef struct busy_info BusyInfo;
00131 
00132 // Client Struct State flags, taken from structs.h of Matchbox WM 1.2
00133 #define CLIENT_IS_SPLASH_WIN      (1<<0)
00134 #define CLIENT_FULLSCREEN_FLAG    (1<<1)
00135 #define CLIENT_TITLE_HIDDEN_FLAG  (1<<2)
00136 #define CLIENT_SHRUNK_FOR_TB_FLAG (1<<3)
00137 #define CLIENT_HELP_BUTTON_FLAG   (1<<4)
00138 #define CLIENT_ACCEPT_BUTTON_FLAG (1<<5)
00139 #define CLIENT_DOCK_NORTH         (1<<6)
00140 #define CLIENT_DOCK_SOUTH         (1<<7)
00141 #define CLIENT_DOCK_EAST          (1<<8)
00142 #define CLIENT_DOCK_WEST          (1<<9)
00143 #define CLIENT_WANTS_MASK_FLAG    (1<<10)
00144 #define CLIENT_IS_MODAL_FLAG      (1<<11)
00145 #define CLIENT_BORDERS_ONLY_FLAG  (1<<12)
00146 #define CLIENT_IS_MESSAGE_DIALOG  (1<<14)
00147 #define CLIENT_IS_DESKTOP_FLAG    (1<<15)
00148 #define CLIENT_NEW_FOR_DESKTOP    (1<<16)
00149 #define CLIENT_DOCK_TITLEBAR      (1<<17)
00150 #define CLIENT_CUSTOM_BUTTON_FLAG (1<<18)
00151 #define CLIENT_IS_MOVING          (1<<19)
00152 #define CLIENT_DOCK_TITLEBAR_SHOW_ON_DESKTOP (1<<20)
00153 #define CLIENT_NO_FOCUS_ON_MAP    (1<<21)
00154 #define CLIENT_IS_MINIMIZED       (1<<23)
00155 #define CLIENT_TOOLBARS_MOVED_FOR_FULLSCREEN (1<<24)
00156 #define CLIENT_IS_TRANSIENT_FOR_ROOT (1<<25)
00157 #define CLIENT_HAS_URGENCY_FLAG   (1<<26)
00158 #define CLIENT_HAS_ABOVE_STATE    (1<<27)
00159 #define CLIENT_IS_MENU_DIALOG     (1<<30)
00160 #define CLIENT_DELAY_MAPPING      (1<<31)
00161 
00162 // Client window types, taken from structs.h of Matchbox WM 1.2
00163 typedef enum 
00164 { 
00165   MBCLIENT_TYPE_DIALOG    = (1<<1),
00166   MBCLIENT_TYPE_TOOLBAR   = (1<<2),
00167   MBCLIENT_TYPE_PANEL     = (1<<3),
00168   MBCLIENT_TYPE_TASK_MENU = (1<<4),
00169   MBCLIENT_TYPE_APP       = (1<<5),
00170   MBCLIENT_TYPE_DESKTOP   = (1<<6),
00171   MBCLIENT_TYPE_OVERRIDE  = (1<<7),
00172   MBCLIENT_TYPE_ANY       = (1<<8)
00173 } MBClientTypeEnum;
00174 
00175 
00176 //----------------------------------------------------------------------------
00177 // Constants
00178 //----------------------------------------------------------------------------
00179 
00180 #define N_FILENAME              1024
00181 #define BUFFERSIZE              1024
00182 #define BUSY_ANIMATION_SPEED    50
00183 
00184 #if MACHINE_IS_DR800SG || MACHINE_IS_DR800S || MACHINE_IS_DR800SW
00185 #define UPDATE_TIMEOUT_NORMAL_PORTRAIT    300 /* can be quicker but increases double updates */
00186 #define UPDATE_TIMEOUT_NORMAL_LANDSCAPE   600
00187 #define UPDATE_TIMEOUT_KEY                 24
00188 #define UPDATE_TIMEOUT_CURSOR              60 /* can be quicker but makes successive updates slower */
00189 #define UPDATE_TIMEOUT_TYPE                60 /* can be quicker but makes successive updates slower */
00190 #define UPDATE_TIMEOUT_SCRIBBLE           150 /* can be quicker but makes successive updates slower */
00191 #define UPDATE_AREA_CONTENT               744*806
00192 #define UPDATE_AREA_FULL                  768*1024
00193 #elif MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00194 #define UPDATE_TIMEOUT_NORMAL_PORTRAIT    450 /* can be quicker but increases double updates */
00195 #define UPDATE_TIMEOUT_NORMAL_LANDSCAPE   900
00196 #define UPDATE_TIMEOUT_KEY                 40
00197 #define UPDATE_TIMEOUT_CURSOR             100 /* can be quicker but makes successive updates slower */
00198 #define UPDATE_TIMEOUT_TYPE               100 /* can be quicker but makes successive updates slower */
00199 #define UPDATE_TIMEOUT_SCRIBBLE           250 /* can be quicker but makes successive updates slower */
00200 #define UPDATE_AREA_CONTENT               1000*1010
00201 #define UPDATE_AREA_FULL                  1024*1280
00202 #else
00203 #error Unhandled machine type
00204 #endif
00205 
00206 
00207 //----------------------------------------------------------------------------
00208 // Static Variables
00209 //----------------------------------------------------------------------------
00210 
00211 static int       fbDev                  = 0;
00212 static int       useSpecialWaveform     = 0;
00213 static guint     g_timeout              = 0;
00214 static DMCommand DisplayCommand;
00215 static uint64_t  deltaAvailableAgain    = 0;
00216 static GSList    *g_ignorelist          = NULL;
00217 
00218 static gboolean g_display_locked        = FALSE;
00219 
00220 
00221 static gboolean locked_display      (void) { return g_display_locked; }
00222 static void lock_display            (void) { g_display_locked = TRUE; }
00223 static void unlock_display          (void) { g_display_locked = FALSE; }
00224 
00225 
00226 static gint delta_update_display(DisplayUpdateInfo *displayUpdateInfo) 
00227 {
00228 //    LOGPRINTF("entry");
00229 
00230     int ret = ioctl(fbDev, FBIO_DELTA_UPDATE_DISPLAY, displayUpdateInfo);
00231     if (ret != 0)
00232     {
00233         ERRORPRINTF("Error sending FBIO_DELTA_UPDATE_DISPLAY: %x", ret);
00234     }
00235     return ret;
00236 }
00237 
00238 
00239 static void display_update(gint waveform)
00240 {
00241     DisplayUpdateInfo displayUpdateInfo;
00242     
00243     displayUpdateInfo.color = 0;
00244     displayUpdateInfo.waveform = waveform;
00245     
00246 #if DMLOGGING_ON 
00247     GTimeVal curtime;
00248     g_get_current_time(&curtime);
00249     
00250     DMPPRINTF("\n\n%ld:%3ld update waveform %d\n",
00251            curtime.tv_sec, curtime.tv_usec / 1000, 
00252            displayUpdateInfo.waveform);
00253 #endif
00254 
00255     // perform display update
00256     delta_update_display(&displayUpdateInfo);
00257     
00258     // reset idle timer
00259 //    sys_reset_idle_time();
00260 }
00261 
00262 static void get_arguments(char *pChar, erDmCmd_t * pCmd, int nReqArgs)
00263 {
00264     int     nArg;
00265     int     i;
00266     char    szToken[DM_MAXCHARONLINE];
00267 
00268     for (nArg = 0; nArg < nReqArgs; nArg++)
00269     {
00270         i = 0;
00271         while (*pChar != '\0')
00272         {
00273             szToken[i] = '\0';
00274             if (*pChar == ',')
00275             {
00276                 pChar++;
00277                 break;
00278             }
00279             szToken[i] = *pChar++;
00280             i++;
00281             szToken[i] = '\0';
00282         }
00283         strcpy(pCmd->arg[nArg], szToken);
00284     }
00285 }
00286 
00287 static gint parse_message(char *szCommand, erDmCmd_t * pCmd)
00288 {
00289     LOGPRINTF("entry");
00290     
00291     int     i;
00292     char   *pChar;
00293     char    szToken[DM_MAXCHARONLINE];
00294 
00295     pCmd->cc = (int) DM_UNDEFINED;
00296     for (i = 0; i < DM_N_ARG; i++)
00297     {
00298         strcpy(pCmd->arg[i], "");
00299     }
00300 
00301     // parse command, form of a command is: !n1,n2,n3...
00302     if (szCommand[0] != '!')
00303     {
00304         ERRORPRINTF("Command should start with \'!\'. (%s)", szCommand);
00305         return -1;
00306     }
00307 
00308     // move beyond initial '!'
00309     pChar = szCommand + 1;
00310     i = 0;
00311     while (*pChar != '\0')
00312     {
00313         szToken[i] = '\0';
00314         if (*pChar == ',')
00315         {
00316             pChar++;
00317             break;
00318         }
00319         szToken[i] = *pChar++;
00320         i++;
00321         szToken[i] = '\0';
00322     }
00323 
00324     // we have found the command token, figure out what the command is
00325     if (!strcmp(szToken, "I"))
00326     {
00327         strcpy(pCmd->name, szToken);
00328         pCmd->cc = DM_INFO;
00329         pCmd->nArg = 10;
00330     }
00331     else if (!strcmp(szToken, "F"))
00332     {
00333         strcpy(pCmd->name, szToken);
00334         pCmd->cc = DM_FORCE;
00335         pCmd->nArg = 3;
00336     }
00337     else
00338     {
00339         return -1;
00340     }
00341 
00342     if (pCmd->nArg > 0)
00343     {
00344         get_arguments(pChar, pCmd, pCmd->nArg);
00345     }
00346     return 0;
00347 }
00348 
00349 
00350 static uint64_t getCurrentTime() 
00351 {
00352     struct timespec now;
00353 
00354     clock_gettime(CLOCK_MONOTONIC, &now);
00355     u_int64_t now64 = now.tv_sec;
00356     now64 *= 1000000;
00357     now64 += (now.tv_nsec/1000);
00358     return now64;
00359 }
00360 
00361 static gint parse_command(erDmCmd_t *pCmd, DMCommand *command)
00362 {
00363     switch (pCmd->cc)
00364     {
00365     case DM_INFO:
00366         command->cmd                = DM_INFO;
00367         command->info.pid           = atoi(pCmd->arg[0]);
00368         command->info.x             = atoi(pCmd->arg[1]);
00369         command->info.y             = atoi(pCmd->arg[2]);
00370         command->info.w             = atoi(pCmd->arg[3]);
00371         command->info.h             = atoi(pCmd->arg[4]);
00372         command->info.shouldIgnore  = atoi(pCmd->arg[5]);
00373         command->info.isWindow      = atoi(pCmd->arg[6]);
00374         command->info.windowType    = atoi(pCmd->arg[7]);
00375         strcpy(command->info.widgetType,pCmd->arg[8]);   
00376         command->info.isFocus       = atoi(pCmd->arg[9]);
00377         break;
00378 
00379     case DM_FORCE:
00380         command->cmd                = DM_FORCE;
00381         command->force.pid          = atoi(pCmd->arg[0]);
00382         command->force.takeControl  = atoi(pCmd->arg[1]);
00383         command->force.hint         = atoi(pCmd->arg[2]);
00384         break;
00385 
00386     default:
00387         ERRORPRINTF("Undefined command");
00388         return -1;
00389         break;
00390     }
00391     return 0;
00392 }
00393 
00394 static gboolean on_message_timeout(gpointer data)
00395 {
00396     LOGPRINTF("entry");
00397     
00398     gint waveform = WAVEFORM_FULL;
00399     
00400     if (useSpecialWaveform != 0)
00401     {
00402         waveform = useSpecialWaveform;
00403     }
00404 
00405     // set time when delta is available again
00406     deltaAvailableAgain = getCurrentTime();
00407     if ((waveform == WAVEFORM_FULL) || (waveform == WAVEFORM_PARTIAL)) 
00408     {
00409         deltaAvailableAgain += DELTA_TIME_FULL;
00410     } 
00411     else if (waveform == WAVEFORM_QUICK) 
00412     {
00413         deltaAvailableAgain += DELTA_TIME_QUICK;
00414     }
00415     
00416     // reset display command
00417     bzero(&DisplayCommand, sizeof(DMCommand));
00418     useSpecialWaveform = 0;
00419     
00420     // perform display update
00421     display_update(waveform);
00422     
00423     // stop timeout
00424     return FALSE;
00425 }
00426 
00427 
00428 static gboolean ignore_pid(gint pid)
00429 {
00430     // just test if ANY pid ignored
00431     return (g_slist_length(g_ignorelist) > 0);
00432 }
00433 
00434 
00435 static void ignore_pid_add(gint pid)
00436 {
00437     LOGPRINTF("entry [%d]", pid);
00438 
00439     GSList *found = g_slist_find(g_ignorelist, (gconstpointer) pid);
00440     if (found == NULL) 
00441     {
00442         LOGPRINTF("added [%d]", pid);
00443         g_ignorelist = g_slist_prepend(g_ignorelist, (gpointer) pid);
00444     }
00445 }
00446 
00447 
00448 static void ignore_pid_remove(gint pid)
00449 {
00450     LOGPRINTF("entry [%d]", pid);
00451     g_ignorelist = g_slist_remove(g_ignorelist, (gpointer) pid);
00452 }
00453 
00454 static void schedule_update(gint delay, const char *rule)
00455 {
00456     // check if sending screen updates too fast
00457     uint64_t now = getCurrentTime();
00458 #if DMLOGGING_ON
00459     guint prev_delay = delay;
00460 #endif                
00461     // adjust delay to after delta is available again
00462     // except when time was set back as deltaAvailableAgain can't be trusted then
00463     if (((deltaAvailableAgain != 0) && ((now + delay*1000) < deltaAvailableAgain))
00464         && ((deltaAvailableAgain - DELTA_TIME_FULL) < now))
00465     {
00466         delay = (deltaAvailableAgain - now) / 1000;
00467     }
00468 
00469     // set new timeout
00470     if (g_timeout > 0) {  
00471         DMPPRINTF("cancel t/o [%d]", g_timeout);
00472         g_source_remove(g_timeout);
00473         g_timeout= 0;
00474     }
00475     g_timeout = g_timeout_add(delay, on_message_timeout, NULL);
00476     
00477     DMPPRINTF("set delay %d [was %d] (rule: %s) t/o [%d]", delay, prev_delay, rule, g_timeout);
00478 }
00479 
00480 
00481 
00482 static void promote_waveform(gint waveform)
00483 {
00484     if (useSpecialWaveform == waveform)
00485         return;
00486     
00487     switch (waveform)
00488     {
00489     case WAVEFORM_QUICK: 
00490         if (useSpecialWaveform == 0)
00491         {
00492             useSpecialWaveform = waveform;
00493         }
00494         break;
00495                 
00496     case WAVEFORM_PARTIAL: 
00497         if ((useSpecialWaveform == 0) || (useSpecialWaveform  == WAVEFORM_QUICK))
00498         {
00499             useSpecialWaveform = waveform;
00500         }
00501         break;
00502                 
00503     case WAVEFORM_FULL: 
00504     default: 
00505         useSpecialWaveform = waveform;
00506         break;
00507     }
00508 }
00509       
00510 
00511 
00512 static gint delta_vcom_set(gfloat vcom)
00513 {
00514     LOGPRINTF("entry");
00515 
00516     glong vcom_int = 0;
00517     gint ret = 0;
00518     
00519     if(vcom < -5) 
00520     {
00521         vcom = -5;
00522     }
00523     else if(vcom > 5) 
00524     {
00525         vcom = 5;
00526     }
00527     
00528     vcom_int = (signed long)(1000 * vcom);
00529     
00530     if ((ret=ioctl(fbDev, FBIO_DETA_VCOM_SET, &vcom_int)))
00531     { 
00532         ERRORPRINTF("Error sending FBIO_DETA_VCOM_SET: %x",ret); 
00533     }
00534     
00535     return ret;    
00536 }
00537 
00538 
00539 static void parse_gtk_messages(char* buffer)
00540 {    
00541 #if DMLOGGING_ON
00542     GTimeVal   oldtime = {0};
00543 #endif    
00544     DMCommand  command;
00545     erDmCmd_t  cmd;
00546 
00547     LOGPRINTF("entry");
00548 
00549     bzero(&command, sizeof(command));
00550 
00551     if ((parse_message(buffer, &cmd)==0) && (parse_command(&cmd, &command) == 0))
00552     {
00553 #if DMLOGGING_ON
00554         GTimeVal curtime;
00555         g_get_current_time(&curtime);
00556         
00557         guint timediff = ((curtime.tv_sec - oldtime.tv_sec) * 1000) + 
00558             ((curtime.tv_usec / 1000 ) - (oldtime.tv_usec / 1000));
00559 #endif
00560 
00561         if (command.cmd == DM_FORCE)
00562         {
00563             DMCommandForce force = command.force;
00564             
00565             DMPPRINTF("%ld:%3ld [%4d] checking msg: %d, %d, %d", 
00566                 curtime.tv_sec, curtime.tv_usec / 1000, timediff, 
00567                 force.pid, force.takeControl, force.hint); 
00568 
00569             if (force.takeControl > 0)
00570             {
00571                 DMPPRINTF(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
00572                 ignore_pid_add(force.pid);
00573                 if (!locked_display())
00574                 {
00575                     DMPPRINTF("cancel pending update");
00576                     // cancel pending update
00577                     bzero(&DisplayCommand, sizeof(DMCommand));
00578                     if (g_timeout > 0) 
00579                     { 
00580                         g_source_remove(g_timeout);
00581                         g_timeout = 0;
00582                     }
00583                 }
00584             }
00585             else
00586             {
00587                 DMPPRINTF("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
00588                 ignore_pid_remove(force.pid);
00589             }
00590             
00591             if (force.hint != DM_HINT_NONE)
00592             {
00593                 gint update_delay = 50;
00594                 switch (force.hint)
00595                 {
00596                     case DM_HINT_LOCK:
00597                         lock_display();
00598                         break;
00599                     case DM_HINT_UNLOCK:
00600                         unlock_display();
00601                         break;
00602                     case DM_HINT_FULL:
00603                         useSpecialWaveform = WAVEFORM_FULL;
00604                         break;
00605                     case DM_HINT_SPLASH:
00606                         update_delay = UPDATE_TIMEOUT_NORMAL_PORTRAIT;
00607                         useSpecialWaveform = WAVEFORM_FULL;
00608                         break;
00609                     case DM_HINT_CURSOR:
00610                         useSpecialWaveform = WAVEFORM_QUICK;
00611                         break;
00612                     case DM_HINT_PARTIAL:
00613                         useSpecialWaveform = WAVEFORM_PARTIAL;
00614                         break;
00615                     case DM_HINT_KEY:
00616                         update_delay = 20;
00617                         useSpecialWaveform = WAVEFORM_QUICK;
00618                         break;
00619                     default:
00620                         WARNPRINTF("unsupported display manager hint [%d]", force.hint);
00621                         useSpecialWaveform = WAVEFORM_FULL;
00622                         break;
00623                 }
00624 /*                
00625                 if (sys_get_orientation() != ORIENTATION_PORTRAIT)
00626                 {
00627                     // account for slower updates when display is rotated
00628                     switch (force.hint)
00629                     {
00630                         case DM_HINT_FULL:
00631                             update_delay = UPDATE_TIMEOUT_NORMAL_LANDSCAPE;
00632                             break;
00633                         case DM_HINT_SPLASH:
00634                             // splash screens are shown in portrait mode
00635                             update_delay = UPDATE_TIMEOUT_NORMAL_PORTRAIT; 
00636                             break;
00637                         case DM_HINT_PARTIAL:
00638                             update_delay = 200;
00639                             break;
00640                         case DM_HINT_CURSOR:
00641                         case DM_HINT_KEY:
00642                             update_delay = 150;
00643                             break;
00644                         case DM_HINT_LOCK:
00645                         case DM_HINT_UNLOCK:
00646                             break;
00647                         default:
00648                             WARNPRINTF("unsupported display manager hint [%d]", force.hint);
00649                             break;
00650                     }
00651                 }
00652 */                    
00653                 if ( !locked_display() || (force.hint == DM_HINT_SPLASH) )
00654                 {
00655                     schedule_update(update_delay, "forced by application");
00656                 }
00657             }
00658         }
00659         else if (command.cmd == DM_INFO) 
00660         {
00661             DMCommandInfo  info  = command.info;
00662             const gchar   *rule        = NULL;
00663             gboolean      save         = FALSE;
00664             gboolean      trigger      = FALSE;
00665             gboolean      skip         = FALSE;
00666             guint         area_pending = DisplayCommand.info.w * DisplayCommand.info.h;
00667             gboolean      is_portait   = TRUE;
00668 //                gboolean      is_portait   = (sys_get_orientation() == ORIENTATION_PORTRAIT) ? TRUE : FALSE;
00669             gboolean      is_pending   = (area_pending > 0) ? TRUE : FALSE;
00670             guint          delay        = is_portait ? UPDATE_TIMEOUT_NORMAL_PORTRAIT : UPDATE_TIMEOUT_NORMAL_LANDSCAPE;
00671             guint         area         = info.w * info.h;
00672             
00673             if ((info.pid != -1) && ignore_pid(info.pid) && 
00674                 (strcmp(info.widgetType,"erGtkBusyDialog") != 0) && (strcmp(info.widgetType,"GtkMessageDialog") != 0))
00675             {
00676                 // skip updates when busy or loading dialog is shown
00677                 skip = TRUE;
00678             }
00679 
00680             DMPPRINTF("%ld:%3ld [%4d] %s pid [%d] %4dx%4d flags: i[%d] w[%d] t[%d] f[%d] %s",
00681                 curtime.tv_sec, curtime.tv_usec / 1000, timediff, skip ? "SKIPPED" : "checking", 
00682                 info.pid, info.w, info.h, info.shouldIgnore,
00683                 info.isWindow, info.windowType, info.isFocus,
00684                 info.widgetType);
00685             
00686             //
00687             // SPECIAL RULES - pre
00688             //
00689            
00690             if (!is_pending && info.h == 32 &&
00691                 strcmp(info.widgetType, "GtkEventBox") == 0)
00692             {
00693                 rule = "statusbar";
00694                 promote_waveform(WAVEFORM_PARTIAL);
00695                 save  = TRUE;
00696             }
00697 
00698             if (!is_pending && strcmp(info.widgetType,"GtkEntry")==0)
00699             {
00700                 rule = "keyboard entry";
00701                 promote_waveform( WAVEFORM_QUICK);
00702                 delay = UPDATE_TIMEOUT_TYPE;
00703                 save  = TRUE;
00704             }
00705             
00706             //
00707             // GENERAL RULES
00708             //
00709 
00710             if (!info.shouldIgnore ||
00711                 (strcmp(info.widgetType,"HtmlView")         == 0) || /* for libgtkhtml */
00712                 (strcmp(info.widgetType,"GtkDrawingArea")   == 0) ||
00713                 (strcmp(info.widgetType,"GtkCalendar")      == 0) ||
00714                 (strcmp(info.widgetType,"GtkTreeView")      == 0) ||
00715                 (strcmp(info.widgetType,"GtkIconView")      == 0) ||
00716                 (strcmp(info.widgetType,"erGtkIconView")    == 0) ||
00717                 (strcmp(info.widgetType,"erGtkListView")    == 0) ||
00718                 (strcmp(info.widgetType,"erGtkNetworkList") == 0) ||
00719                 (strcmp(info.widgetType,"WebKitWebView")    == 0) ||
00720                 (strcmp(info.widgetType,"GtkMenu")          == 0) ||
00721                 (strcmp(info.widgetType,"GtkProgressBar")   == 0) )
00722             {
00723                 if (!is_pending &&
00724                     info.isFocus && 
00725                     (area<UPDATE_AREA_CONTENT) &&
00726                     ((strcmp(info.widgetType, "erGtkIconView") == 0) ||
00727                      (strcmp(info.widgetType, "erGtkNetworkList") == 0) ||
00728                      (strcmp(info.widgetType, "erGtkListView") == 0)) ) 
00729                 {
00730                     rule = "cursor";
00731                     promote_waveform(WAVEFORM_QUICK);
00732                     delay = is_portait ? UPDATE_TIMEOUT_CURSOR : 3*UPDATE_TIMEOUT_CURSOR;
00733                     save  = TRUE;
00734                 }
00735 /*                    
00736                 else if (strcmp(WindowInfo.name, "erbrowser") == 0)
00737                 {
00738                     if ( !((strcmp(info.widgetType, "GtkWindow") == 0) && is_pending)
00739                         && ((area * 3) < UPDATE_AREA_FULL) )
00740                     {
00741                         rule = "paint, partial (browser)";
00742                         promote_waveform(WAVEFORM_PARTIAL);
00743                     }
00744                     else
00745                     {
00746                         rule = "paint, full (browser)";
00747                         promote_waveform(WAVEFORM_FULL);
00748                         delay = 1000;
00749                     }
00750                     save = TRUE;
00751                 }
00752 */                    
00753                 else if (area > area_pending)
00754                 {
00755                     if ((area * 3) < UPDATE_AREA_FULL)
00756                     {
00757                         promote_waveform(WAVEFORM_PARTIAL);
00758                         rule = "paint, partial";
00759                     }
00760                     else
00761                     {
00762                         promote_waveform(WAVEFORM_FULL);
00763                         rule = "paint, full";
00764                         
00765                         if (is_portait && strcmp(info.widgetType,"GtkDrawingArea") == 0)
00766                         {
00767                             rule = "paint, full (UDS)";
00768                             delay /= 2;
00769                         }
00770                     }
00771                     save = TRUE;
00772                 }
00773                 else if (is_pending)
00774                 {
00775                     if (is_portait && strcmp(info.widgetType,"erGtkIconView")  == 0)
00776                     {
00777                         delay /= 2;
00778                     }
00779                     rule    = "delay";
00780                     trigger = TRUE;
00781                 }
00782             }
00783             
00784             //
00785             // SPECIAL RULES - post - override general rules
00786             //
00787            
00788             if (!is_pending && info.h == 29 && 
00789                 ((strcmp(info.widgetType,"GtkMessageDialog")==0) ||
00790                  (strcmp(info.widgetType,"GtkDialog")==0)))
00791             {
00792                 rule = "button cursor";
00793                 useSpecialWaveform = WAVEFORM_QUICK;
00794                 delay = is_portait ? UPDATE_TIMEOUT_CURSOR : 2*UPDATE_TIMEOUT_CURSOR;
00795                 save  = TRUE;
00796             }
00797             
00798             if (!is_pending && strcmp(info.widgetType,"erscribble")==0)
00799             {
00800                 rule = "scribble";
00801                 useSpecialWaveform = WAVEFORM_PARTIAL;
00802                 delay = UPDATE_TIMEOUT_SCRIBBLE;
00803                 save  = TRUE;
00804             }
00805             
00806             // NOTE: check is_pending
00807             if (is_pending && 
00808                 (useSpecialWaveform != WAVEFORM_FULL) &&
00809                 ( (strcmp(info.widgetType, "WebKitWebView")==0) ||
00810                   (strcmp(info.widgetType, "GtkEntry")==0) ) )
00811             {
00812                 rule = "entry speedup";
00813                 save = FALSE;
00814                 delay /= 2;
00815                 trigger = FALSE;
00816             }
00817             
00818             //
00819             // Save command and (re)set timeout
00820             //
00821             
00822             if (save)
00823             {
00824                 DMPPRINTF("%ld:%3ld save area %d (rule: %s)", curtime.tv_sec, curtime.tv_usec / 1000, area, rule);
00825                 
00826                 memcpy(&DisplayCommand, &command, sizeof(DMCommand));
00827                 trigger = TRUE;
00828             }
00829                 
00830             if (trigger && !skip)
00831             {
00832                 schedule_update(delay, rule);
00833             }
00834         }
00835 #if DMLOGGING_ON
00836         memcpy(&oldtime, &curtime, sizeof(GTimeVal));
00837 #endif                
00838     }
00839 }
00840 
00841 
00842 
00843 gboolean handle_gtk_socket(GIOChannel* source, GIOCondition condition, gpointer data)
00844 {
00845     UNUSED(data);
00846     
00847     LOGPRINTF("entry");
00848     
00849     if (condition != G_IO_IN) {
00850         WARNPRINTF("%s() UNKNOWN CONDITION (%d)", __func__, condition);
00851         return FALSE;
00852     }
00853 
00854     gchar *buffer = NULL;
00855     gsize last_byte = 0;
00856     gsize bytes_read = 0;
00857     GError *error = NULL;
00858     g_io_channel_read_line(source, &buffer, &bytes_read, &last_byte, &error);
00859     buffer[last_byte] = '\0';
00860     if (error) {
00861         WARNPRINTF("GTK socket read failed: %s", error->message);
00862         g_error_free(error);
00863     } else {
00864         parse_gtk_messages(buffer);
00865     }
00866     g_free(buffer);
00867     return TRUE;    // keep listening
00868 } 
00869 
00870 
00871 int main(int argc, char *argv[])
00872 {
00873     GMainLoop* gloop;
00874     g_type_init();
00875     gloop = g_main_loop_new(NULL, FALSE);
00876 
00877     // open framebuffer device
00878     fbDev = open("/dev/fb0", O_RDWR);
00879     if (fbDev == -1)
00880     {
00881         ERRORPRINTF("Cannot open framebufferdevice. # mknod /dev/fb0 c 29 0");
00882         return 0;
00883     }
00884 
00885     // add GIOChannel for WM socket
00886     int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
00887     if (sockfd == -1) {
00888         perror("Error invoking socket");
00889         return 0;
00890     }
00891     struct sockaddr_in server_addr;
00892     bzero(&server_addr, sizeof(struct sockaddr_in));
00893     server_addr.sin_family = AF_INET;
00894     server_addr.sin_port = htons(DMPORT);
00895     server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
00896     memset(server_addr.sin_zero, 0, sizeof(server_addr.sin_zero));
00897 
00898     int error = bind(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr));
00899     if (error) {
00900         perror("Error invoking bind");
00901         return 0;
00902     }
00903     GIOChannel* channel = g_io_channel_unix_new(sockfd);
00904     g_io_channel_set_encoding(channel, NULL, NULL);
00905     g_io_add_watch(channel, G_IO_IN|G_IO_PRI|G_IO_ERR, handle_gtk_socket, NULL);
00906     
00907     // init VCOM for delta driver
00908     delta_vcom_set(-2.7);
00909 
00910     // run the main loop
00911     LOGPRINTF("before g_main_loop_run");
00912     g_main_loop_run(gloop);
00913     LOGPRINTF("after g_main_loop_run");
00914     
00915     return 0;
00916 }
00917 
Generated by  doxygen 1.6.2-20100208