00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "config.h"
00032
00033
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 #include <pthread.h>
00044
00045
00046 #include <liberipc/eripc.h>
00047 #include <liberipc/eripc_support.h>
00048 #include <liberutils/display_utils.h>
00049
00050
00051 #include "log.h"
00052 #include "delta.h"
00053 #include "system.h"
00054 #include "tasks.h"
00055 #include "xwindow.h"
00056 #include "ipc.h"
00057
00058 #define UNUSED(x) (void)(x)
00059
00060
00061
00062
00063
00064
00065
00066 #define DMPORT 50555
00067 #define LOCALHOST 0x7f000001L // "127.0.0.1"
00068
00069 #define DM_MAXCHARONLINE 1024
00070 #define DM_CMD_NAME 128
00071 #define DM_ARGLENGTH 256
00072 #define DM_N_ARG 16
00073
00074
00075 #define WMPORT 50556
00076 #define WM_NAME 64
00077
00078 #define WAVEFORM_QUICK 6 // WAVEFORM_1BPP_IMAGE
00079 #define WAVEFORM_PARTIAL 9 // WAVEFORM_2BPP_IMAGE
00080 #define WAVEFORM_FULL 1 // WAVEFORM_4BPP_IMAGE
00081
00082
00083 #define DELTA_TIME_FULL 900*1000
00084
00085 #define DELTA_TIME_QUICK 50*1000
00086
00087 typedef enum
00088 {
00089 DM_INFO,
00090 DM_FORCE,
00091 DM_UNDEFINED
00092 } DMCommandCode;
00093
00094 typedef struct
00095 {
00096 int pid;
00097 int x, y;
00098 int w, h;
00099 int shouldIgnore;
00100 int isWindow;
00101 int windowType;
00102 char widgetType[64];
00103 int isFocus;
00104 } DMCommandInfo;
00105
00106 typedef struct
00107 {
00108 int pid;
00109 int takeControl;
00110 int hint;
00111 } DMCommandForce;
00112
00113 typedef struct
00114 {
00115 DMCommandCode cmd;
00116 DMCommandInfo info;
00117 DMCommandForce force;
00118 } DMCommand;
00119
00120 typedef struct
00121 {
00122 char name[DM_CMD_NAME];
00123 int cc;
00124 char arg[DM_N_ARG][DM_ARGLENGTH];
00125 int nArg;
00126 } erDmCmd_t;
00127
00128 typedef struct
00129 {
00130 char name[WM_NAME];
00131 int window;
00132 int type;
00133 long flags;
00134 int pid;
00135 } WMInfo;
00136
00137
00138 typedef struct display_update_info DisplayUpdateInfo;
00139 typedef struct wave_info WaveInfo;
00140 typedef struct busy_info BusyInfo;
00141
00142
00143 #define CLIENT_IS_SPLASH_WIN (1<<0)
00144 #define CLIENT_FULLSCREEN_FLAG (1<<1)
00145 #define CLIENT_TITLE_HIDDEN_FLAG (1<<2)
00146 #define CLIENT_SHRUNK_FOR_TB_FLAG (1<<3)
00147 #define CLIENT_HELP_BUTTON_FLAG (1<<4)
00148 #define CLIENT_ACCEPT_BUTTON_FLAG (1<<5)
00149 #define CLIENT_DOCK_NORTH (1<<6)
00150 #define CLIENT_DOCK_SOUTH (1<<7)
00151 #define CLIENT_DOCK_EAST (1<<8)
00152 #define CLIENT_DOCK_WEST (1<<9)
00153 #define CLIENT_WANTS_MASK_FLAG (1<<10)
00154 #define CLIENT_IS_MODAL_FLAG (1<<11)
00155 #define CLIENT_BORDERS_ONLY_FLAG (1<<12)
00156 #define CLIENT_IS_MESSAGE_DIALOG (1<<14)
00157 #define CLIENT_IS_DESKTOP_FLAG (1<<15)
00158 #define CLIENT_NEW_FOR_DESKTOP (1<<16)
00159 #define CLIENT_DOCK_TITLEBAR (1<<17)
00160 #define CLIENT_CUSTOM_BUTTON_FLAG (1<<18)
00161 #define CLIENT_IS_MOVING (1<<19)
00162 #define CLIENT_DOCK_TITLEBAR_SHOW_ON_DESKTOP (1<<20)
00163 #define CLIENT_NO_FOCUS_ON_MAP (1<<21)
00164 #define CLIENT_IS_MINIMIZED (1<<23)
00165 #define CLIENT_TOOLBARS_MOVED_FOR_FULLSCREEN (1<<24)
00166 #define CLIENT_IS_TRANSIENT_FOR_ROOT (1<<25)
00167 #define CLIENT_HAS_URGENCY_FLAG (1<<26)
00168 #define CLIENT_HAS_ABOVE_STATE (1<<27)
00169 #define CLIENT_IS_MENU_DIALOG (1<<30)
00170 #define CLIENT_DELAY_MAPPING (1<<31)
00171
00172
00173 typedef enum
00174 {
00175 MBCLIENT_TYPE_DIALOG = (1<<1),
00176 MBCLIENT_TYPE_TOOLBAR = (1<<2),
00177 MBCLIENT_TYPE_PANEL = (1<<3),
00178 MBCLIENT_TYPE_TASK_MENU = (1<<4),
00179 MBCLIENT_TYPE_APP = (1<<5),
00180 MBCLIENT_TYPE_DESKTOP = (1<<6),
00181 MBCLIENT_TYPE_OVERRIDE = (1<<7),
00182 MBCLIENT_TYPE_ANY = (1<<8)
00183 } MBClientTypeEnum;
00184
00185
00186
00187
00188
00189
00190 #define N_FILENAME 1024
00191 #define BUFFERSIZE 1024
00192 #define BUSY_ANIMATION_SPEED 50
00193
00194 #if MACHINE_IS_DR800SG || MACHINE_IS_DR800S || MACHINE_IS_DR800SW
00195 #define UPDATE_TIMEOUT_FORCED 50
00196 #define UPDATE_TIMEOUT_NORMAL_PORTRAIT 300
00197 #define UPDATE_TIMEOUT_NORMAL_LANDSCAPE 600
00198 #define UPDATE_TIMEOUT_KEY 24
00199 #define UPDATE_TIMEOUT_CURSOR 60
00200 #define UPDATE_TIMEOUT_TYPE 60
00201 #define UPDATE_TIMEOUT_SCRIBBLE 150
00202 #define UPDATE_AREA_CONTENT 744*806
00203 #define UPDATE_AREA_FULL 768*1024
00204 #elif MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00205 #define UPDATE_TIMEOUT_FORCED 80
00206 #define UPDATE_TIMEOUT_NORMAL_PORTRAIT 450
00207 #define UPDATE_TIMEOUT_NORMAL_LANDSCAPE 900
00208 #define UPDATE_TIMEOUT_KEY 40
00209 #define UPDATE_TIMEOUT_CURSOR 100
00210 #define UPDATE_TIMEOUT_TYPE 100
00211 #define UPDATE_TIMEOUT_SCRIBBLE 250
00212 #define UPDATE_AREA_CONTENT 1000*1010
00213 #define UPDATE_AREA_FULL 1024*1280
00214 #else
00215 #error Unhandled machine type
00216 #endif
00217
00218
00219
00220
00221
00222
00223 static int fbDev = 0;
00224 static int useSpecialWaveform = 0;
00225 static DMCommand DisplayCommand;
00226 static WMInfo WindowInfo;
00227 static uint64_t deltaAvailableAgain = 0;
00228 static GSList *g_ignorelist = NULL;
00229
00230 static int g_ctb_window = 0;
00231 static int g_prev_window = 0;
00232 static gboolean g_display_locked = FALSE;
00233 static gboolean g_vcom_is_set = FALSE;
00234
00235 static pthread_t dm_thread;
00236 static struct timeval g_timeout;
00237
00238
00239
00240
00241
00242
00243 static gboolean handle_gtk_socket (GIOChannel* source, GIOCondition condition, gpointer data);
00244 static gint parse_message (char *szCommand, erDmCmd_t *pCmd);
00245 static gint parse_command (erDmCmd_t *pCmd, DMCommand *command);
00246 static void get_arguments (char *pChar, erDmCmd_t * pCmd, int nReqArgs);
00247 static void on_message_timeout (void);
00248 static void* gtk_messages (void *arg);
00249 static void display_update (gint waveform);
00250 static void schedule_update (gint delay, const char *rule);
00251
00252 static gint delta_vcom_set (gfloat vcom);
00253 static int delta_uploadwave (char *filename, glong offset);
00254 static gint delta_erase (gint color);
00255 static gint delta_update_display (DisplayUpdateInfo *displayUpdateInfo);
00256 static gint delta_busy (gint xpos, gint ypos, gint speed);
00257 static void delta_init (void);
00258
00259 static gboolean ignore_pid (gint pid);
00260 static void ignore_pid_add (gint pid);
00261 static void ignore_pid_remove (gint pid);
00262
00263 static gboolean locked_display (void) { return g_display_locked; }
00264 static void lock_display (void) { g_display_locked = TRUE; }
00265 static void unlock_display (void) { g_display_locked = FALSE; }
00266
00267
00268
00269
00270
00271
00272 static void parse_wm_messages(char* buffer)
00273 {
00274
00275 gchar **args = g_strsplit_set(buffer, ",", 4);
00276
00277 gint window = atoi(args[0]);
00278 gint type = atoi(args[1]);
00279 glong flags = atol(args[2]);
00280 gchar *endp = strchr(args[3], ' ');
00281 if (endp) {
00282 *endp = '\0';
00283 }
00284 gchar *name = args[3];
00285
00286 proc_t *proc = process_get_by_name(name);
00287
00288 if ( ((type & MBCLIENT_TYPE_DIALOG) == MBCLIENT_TYPE_DIALOG) &&
00289 ((flags & CLIENT_IS_MENU_DIALOG) != CLIENT_IS_MENU_DIALOG) )
00290 {
00291 DMPPRINTF("ignored dialog, window [%d] name [%s] pid [%d]", WindowInfo.window, name, proc ? proc->pid : -1);
00292 }
00293 else
00294 {
00295 if ( (g_prev_window != window) &&
00296 ((flags & CLIENT_IS_MENU_DIALOG) != CLIENT_IS_MENU_DIALOG) )
00297 {
00298 LOGPRINTF("changed window and not menu, deactivate previous: %d", g_prev_window);
00299
00300
00301 if (g_prev_window > 0)
00302 {
00303 const gchar *service = task_service_by_window(g_prev_window);
00304 if (service)
00305 {
00306 ipc_send_window_deactivated(service, g_prev_window);
00307 }
00308 else if (g_ctb_window != 0 && g_prev_window == g_ctb_window)
00309 {
00310 ipc_send_window_deactivated("com.irexnet.ctb", g_ctb_window);
00311 }
00312 }
00313
00314 if (window > 0)
00315 {
00316
00317 const gchar *service = task_service_by_window(window);
00318 if (service)
00319 {
00320 ipc_send_window_activated(service, window);
00321 }
00322 else if (g_ctb_window != 0 && window == g_ctb_window)
00323 {
00324 ipc_send_window_activated("com.irexnet.ctb", g_ctb_window);
00325 }
00326 }
00327 g_prev_window = window;
00328 }
00329
00330
00331 strncpy(WindowInfo.name, name, WM_NAME);
00332 WindowInfo.name[WM_NAME-1] = '\0';
00333 WindowInfo.window = window;
00334 WindowInfo.type = type;
00335 WindowInfo.flags = flags;
00336 WindowInfo.pid = proc ? proc->pid : -1;
00337
00338 DMPPRINTF("set window info [%d] type [%d] flags [%ld] name [%s] pid [%d]",
00339 WindowInfo.window, WindowInfo.type, WindowInfo.flags, WindowInfo.name,
00340 WindowInfo.pid);
00341 }
00342
00343
00344 useSpecialWaveform = WAVEFORM_FULL;
00345
00346 g_strfreev(args);
00347 }
00348
00349
00350 gboolean handle_wm_socket(GIOChannel* source, GIOCondition condition, gpointer data)
00351 {
00352 UNUSED(data);
00353
00354 if (condition != G_IO_IN) {
00355 WARNPRINTF("%s() UNKNOWN CONDITION (%d)", __func__, condition);
00356 return FALSE;
00357 }
00358
00359 gchar* buffer = NULL;
00360 gsize bytes_read = 0;
00361 gsize last_byte = 0;
00362 GError *error = NULL;
00363 g_io_channel_read_line(source, &buffer, &bytes_read, &last_byte, &error);
00364 buffer[last_byte] = 0;
00365 if (error) {
00366 WARNPRINTF("WM socket read failed: %s", error->message);
00367 g_error_free(error);
00368 } else {
00369 parse_wm_messages(buffer);
00370 }
00371 g_free(buffer);
00372 return TRUE;
00373 }
00374
00375
00376 void display_set_services()
00377 {
00378 LOGPRINTF("entry");
00379
00380 if (pthread_create(&dm_thread, NULL, gtk_messages, NULL) != 0)
00381 {
00382 ERRORPRINTF("Could not create thread");
00383 return;
00384 }
00385
00386
00387
00388 int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
00389 if (sockfd == -1) {
00390 perror("Error invoking socket");
00391 return;
00392 }
00393 bzero(&WindowInfo, sizeof(WMInfo));
00394 struct sockaddr_in server_addr;
00395 bzero(&server_addr, sizeof(struct sockaddr_in));
00396 server_addr.sin_family = AF_INET;
00397 server_addr.sin_port = htons(WMPORT);
00398 server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
00399 memset(server_addr.sin_zero, 0, sizeof(server_addr.sin_zero));
00400
00401 int error = bind(sockfd, &server_addr, sizeof(server_addr));
00402 if (error) {
00403 perror("Error invoking bind");
00404 return;
00405 }
00406 GIOChannel* channel = g_io_channel_unix_new(sockfd);
00407 g_io_channel_set_encoding(channel, NULL, NULL);
00408 g_io_add_watch(channel, G_IO_IN|G_IO_PRI|G_IO_ERR, handle_wm_socket, NULL);
00409 }
00410
00411
00412 void display_blank(void)
00413 {
00414 LOGPRINTF("entry");
00415
00416
00417 if (g_timeout.tv_sec > 0 || g_timeout.tv_usec > 0)
00418 {
00419 bzero(&DisplayCommand, sizeof(DMCommand));
00420 g_timeout.tv_sec = -1;
00421 g_timeout.tv_usec = -1;
00422 }
00423
00424
00425 delta_erase(15);
00426 }
00427
00428
00429 void display_busy_animation(gint xpos, gint ypos)
00430 {
00431 LOGPRINTF("entry: x %d, y %d", xpos, ypos);
00432 delta_busy(xpos, ypos, BUSY_ANIMATION_SPEED);
00433 }
00434
00435
00436 gchar *display_get_active_window(void)
00437 {
00438 LOGPRINTF("entry");
00439 return WindowInfo.name;
00440 }
00441
00442
00443 void display_cleanup_pid(gint pid)
00444 {
00445 LOGPRINTF("entry");
00446 ignore_pid_remove(pid);
00447 }
00448
00449
00450 void display_set_vcom(gfloat vcom)
00451 {
00452 LOGPRINTF("entry [%f]", vcom);
00453 delta_vcom_set(vcom);
00454 }
00455
00456
00457 void display_set_waveforms(void)
00458 {
00459 LOGPRINTF("entry");
00460 delta_uploadwave("/var/tmp/waves", 0);
00461 }
00462
00463
00464 void display_init(void)
00465 {
00466 LOGPRINTF("entry");
00467 delta_init();
00468 }
00469
00470
00471
00472
00473
00474
00475 static uint64_t getCurrentTime()
00476 {
00477 struct timespec now;
00478
00479 clock_gettime(CLOCK_MONOTONIC, &now);
00480 u_int64_t now64 = now.tv_sec;
00481 now64 *= 1000000;
00482 now64 += (now.tv_nsec/1000);
00483 return now64;
00484 }
00485
00486
00487 static gboolean ignore_pid(gint pid)
00488 {
00489
00490 return (g_slist_length(g_ignorelist) > 0);
00491 }
00492
00493
00494 static void ignore_pid_add(gint pid)
00495 {
00496 LOGPRINTF("entry [%d]", pid);
00497
00498 GSList *found = g_slist_find(g_ignorelist, (gconstpointer) pid);
00499 if (found == NULL)
00500 {
00501 LOGPRINTF("added [%d]", pid);
00502 g_ignorelist = g_slist_prepend(g_ignorelist, (gpointer) pid);
00503 }
00504 }
00505
00506
00507 static void ignore_pid_remove(gint pid)
00508 {
00509 LOGPRINTF("entry [%d]", pid);
00510 g_ignorelist = g_slist_remove(g_ignorelist, (gpointer) pid);
00511 }
00512
00513
00514 static void promote_waveform(gint waveform)
00515 {
00516 if (useSpecialWaveform == waveform)
00517 return;
00518
00519 switch (waveform)
00520 {
00521 case WAVEFORM_QUICK:
00522 if (useSpecialWaveform == 0)
00523 {
00524 useSpecialWaveform = waveform;
00525 }
00526 break;
00527
00528 case WAVEFORM_PARTIAL:
00529 if ((useSpecialWaveform == 0) || (useSpecialWaveform == WAVEFORM_QUICK))
00530 {
00531 useSpecialWaveform = waveform;
00532 }
00533 break;
00534
00535 case WAVEFORM_FULL:
00536 default:
00537 useSpecialWaveform = waveform;
00538 break;
00539 }
00540 }
00541
00542
00543 static void parse_gtk_message(char* buffer)
00544 {
00545
00546
00547 #if DMLOGGING_ON
00548 static GTimeVal oldtime = {0};
00549 #endif
00550 erDmCmd_t cmd;
00551 DMCommand command;
00552 bzero(&command, sizeof(command));
00553
00554 if ((parse_message(buffer, &cmd)==0) && (parse_command(&cmd, &command) == 0))
00555 {
00556 #if DMLOGGING_ON
00557 GTimeVal curtime;
00558 g_get_current_time(&curtime);
00559
00560 guint timediff = ((curtime.tv_sec - oldtime.tv_sec) * 1000) +
00561 ((curtime.tv_usec / 1000 ) - (oldtime.tv_usec / 1000));
00562 #endif
00563
00564 if (command.cmd == DM_FORCE)
00565 {
00566 DMCommandForce force = command.force;
00567
00568 DMPPRINTF("%ld:%3ld [%4d] checking msg: %d, %d, %d",
00569 curtime.tv_sec, curtime.tv_usec / 1000, timediff,
00570 force.pid, force.takeControl, force.hint);
00571
00572 if (force.takeControl > 0)
00573 {
00574 DMPPRINTF(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
00575 ignore_pid_add(force.pid);
00576 if (!locked_display() && (g_timeout.tv_sec > 0 || g_timeout.tv_usec > 0))
00577 {
00578
00579 DMPPRINTF("cancel pending update");
00580 bzero(&DisplayCommand, sizeof(DMCommand));
00581 g_timeout.tv_sec = -1;
00582 g_timeout.tv_usec = -1;
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 = UPDATE_TIMEOUT_FORCED;
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 case DM_HINT_SPLASH:
00604 useSpecialWaveform = WAVEFORM_FULL;
00605 break;
00606 case DM_HINT_CURSOR:
00607 useSpecialWaveform = WAVEFORM_QUICK;
00608 break;
00609 case DM_HINT_PARTIAL:
00610 useSpecialWaveform = WAVEFORM_PARTIAL;
00611 break;
00612 case DM_HINT_KEY:
00613 update_delay = 20;
00614 useSpecialWaveform = WAVEFORM_QUICK;
00615 break;
00616 default:
00617 WARNPRINTF("unsupported display manager hint [%d]", force.hint);
00618 useSpecialWaveform = WAVEFORM_FULL;
00619 break;
00620 }
00621
00622 if (sys_get_orientation() != ORIENTATION_PORTRAIT)
00623 {
00624
00625 switch (force.hint)
00626 {
00627 case DM_HINT_FULL:
00628 update_delay = UPDATE_TIMEOUT_NORMAL_LANDSCAPE;
00629 break;
00630 case DM_HINT_SPLASH:
00631
00632 update_delay = UPDATE_TIMEOUT_NORMAL_PORTRAIT;
00633 break;
00634 case DM_HINT_PARTIAL:
00635 update_delay = UPDATE_TIMEOUT_NORMAL_LANDSCAPE;
00636 break;
00637 case DM_HINT_CURSOR:
00638 case DM_HINT_KEY:
00639 update_delay = 150;
00640 break;
00641 case DM_HINT_LOCK:
00642 case DM_HINT_UNLOCK:
00643 break;
00644 default:
00645 WARNPRINTF("unsupported display manager hint [%d]", force.hint);
00646 break;
00647 }
00648 }
00649
00650 if ( (!locked_display() && !(force.hint == DM_HINT_UNLOCK)) || (force.hint == DM_HINT_SPLASH) )
00651 {
00652 schedule_update(update_delay, "forced by application");
00653 }
00654 }
00655 }
00656 else if (command.cmd == DM_INFO)
00657 {
00658 DMCommandInfo info = command.info;
00659 const gchar *rule = NULL;
00660 gboolean save = FALSE;
00661 gboolean trigger = FALSE;
00662 gboolean skip = FALSE;
00663 guint area_pending = DisplayCommand.info.w * DisplayCommand.info.h;
00664 gboolean is_portait = (sys_get_orientation() == ORIENTATION_PORTRAIT) ? TRUE : FALSE;
00665 gboolean is_pending = (area_pending > 0) ? TRUE : FALSE;
00666 guint delay = is_portait ? UPDATE_TIMEOUT_NORMAL_PORTRAIT : UPDATE_TIMEOUT_NORMAL_LANDSCAPE;
00667 guint area = info.w * info.h;
00668
00669 if ((info.pid != -1) && ignore_pid(info.pid) &&
00670 (strcmp(info.widgetType,"erGtkBusyDialog") != 0) && (strcmp(info.widgetType,"GtkMessageDialog") != 0))
00671 {
00672
00673 skip = TRUE;
00674 }
00675
00676 DMPPRINTF("%ld:%3ld [%4d] %s pid [%d] %4dx%4d flags: i[%d] w[%d] t[%d] f[%d] %s",
00677 curtime.tv_sec, curtime.tv_usec / 1000, timediff, skip ? "SKIPPED" : "checking",
00678 info.pid, info.w, info.h, info.shouldIgnore,
00679 info.isWindow, info.windowType, info.isFocus,
00680 info.widgetType);
00681
00682
00683
00684
00685
00686 if (!is_pending && info.h == 32 &&
00687 strcmp(info.widgetType, "GtkEventBox") == 0)
00688 {
00689 rule = "statusbar";
00690 promote_waveform(WAVEFORM_PARTIAL);
00691 save = TRUE;
00692 }
00693
00694 if (!is_pending && strcmp(info.widgetType,"GtkEntry")==0)
00695 {
00696 rule = "keyboard entry";
00697 promote_waveform( WAVEFORM_QUICK);
00698 delay = UPDATE_TIMEOUT_TYPE;
00699 save = TRUE;
00700 }
00701
00702
00703
00704
00705
00706 if (!info.shouldIgnore ||
00707 (strcmp(info.widgetType,"HtmlView") == 0) ||
00708 (strcmp(info.widgetType,"GtkDrawingArea") == 0) ||
00709 (strcmp(info.widgetType,"GtkCalendar") == 0) ||
00710 (strcmp(info.widgetType,"GtkTreeView") == 0) ||
00711 (strcmp(info.widgetType,"GtkIconView") == 0) ||
00712 (strcmp(info.widgetType,"erGtkIconView") == 0) ||
00713 (strcmp(info.widgetType,"erGtkListView") == 0) ||
00714 (strcmp(info.widgetType,"erGtkNetworkList") == 0) ||
00715 (strcmp(info.widgetType,"WebKitWebView") == 0) ||
00716 (strcmp(info.widgetType,"GtkMenu") == 0) ||
00717 (strcmp(info.widgetType,"GtkProgressBar") == 0) )
00718 {
00719 if (!is_pending &&
00720 info.isFocus &&
00721 (area<UPDATE_AREA_CONTENT) &&
00722 ((strcmp(info.widgetType, "erGtkIconView") == 0) ||
00723 (strcmp(info.widgetType, "erGtkNetworkList") == 0) ||
00724 (strcmp(info.widgetType, "erGtkListView") == 0)) )
00725 {
00726 rule = "cursor";
00727 promote_waveform(WAVEFORM_QUICK);
00728 delay = is_portait ? UPDATE_TIMEOUT_CURSOR : 3*UPDATE_TIMEOUT_CURSOR;
00729 save = TRUE;
00730 }
00731 else if (strcmp(WindowInfo.name, "erbrowser") == 0)
00732 {
00733 if ( !((strcmp(info.widgetType, "GtkWindow") == 0) && is_pending)
00734 && ((area * 3) < UPDATE_AREA_FULL) )
00735 {
00736 rule = "paint, partial (browser)";
00737 promote_waveform(WAVEFORM_PARTIAL);
00738 }
00739 else
00740 {
00741 rule = "paint, full (browser)";
00742 promote_waveform(WAVEFORM_FULL);
00743 delay = 1000;
00744 }
00745 save = TRUE;
00746 }
00747 else if (area > area_pending)
00748 {
00749 if ((area * 3) < UPDATE_AREA_FULL)
00750 {
00751 promote_waveform(WAVEFORM_PARTIAL);
00752 rule = "paint, partial";
00753 }
00754 else
00755 {
00756 promote_waveform(WAVEFORM_FULL);
00757 rule = "paint, full";
00758
00759 if (is_portait && strcmp(info.widgetType,"GtkDrawingArea") == 0)
00760 {
00761 rule = "paint, full (UDS)";
00762 delay /= 2;
00763 }
00764 }
00765 save = TRUE;
00766 }
00767 else if (is_pending)
00768 {
00769 if (is_portait && strcmp(info.widgetType,"erGtkIconView") == 0)
00770 {
00771 delay /= 2;
00772 }
00773 rule = "delay";
00774 trigger = TRUE;
00775 }
00776 }
00777
00778
00779
00780
00781
00782 if (!is_pending && info.h == 29 &&
00783 ((strcmp(info.widgetType,"GtkMessageDialog")==0) ||
00784 (strcmp(info.widgetType,"GtkDialog")==0)))
00785 {
00786 rule = "button cursor";
00787 useSpecialWaveform = WAVEFORM_QUICK;
00788 delay = is_portait ? UPDATE_TIMEOUT_CURSOR : 2*UPDATE_TIMEOUT_CURSOR;
00789 save = TRUE;
00790 }
00791
00792 if (!is_pending && strcmp(info.widgetType,"erscribble")==0)
00793 {
00794 rule = "scribble";
00795 useSpecialWaveform = WAVEFORM_PARTIAL;
00796 delay = UPDATE_TIMEOUT_SCRIBBLE;
00797 save = TRUE;
00798 }
00799
00800
00801 if (is_pending &&
00802 (useSpecialWaveform != WAVEFORM_FULL) &&
00803 ( (strcmp(info.widgetType, "WebKitWebView")==0) ||
00804 (strcmp(info.widgetType, "GtkEntry")==0) ) )
00805 {
00806 rule = "entry speedup";
00807 save = FALSE;
00808 delay /= 2;
00809 trigger = FALSE;
00810 }
00811
00812
00813
00814
00815
00816 if (save)
00817 {
00818 DMPPRINTF("%ld:%3ld save area %d (rule: %s)", curtime.tv_sec, curtime.tv_usec / 1000, area, rule);
00819
00820 memcpy(&DisplayCommand, &command, sizeof(DMCommand));
00821 trigger = TRUE;
00822 }
00823
00824 if (trigger && !skip)
00825 {
00826 schedule_update(delay, rule);
00827 }
00828 }
00829 #if DMLOGGING_ON
00830 memcpy(&oldtime, &curtime, sizeof(GTimeVal));
00831 #endif
00832 }
00833 }
00834
00835
00836 static void schedule_update(gint mdelay, const char *rule)
00837 {
00838 gulong udelay;
00839
00840
00841 uint64_t now = getCurrentTime();
00842 #if DMLOGGING_ON
00843 guint prev_delay = mdelay;
00844 #endif
00845
00846
00847 if (((deltaAvailableAgain != 0) && ((now + mdelay*1000) < deltaAvailableAgain))
00848 && ((deltaAvailableAgain - DELTA_TIME_FULL) < now))
00849 {
00850 udelay = (deltaAvailableAgain - now);
00851 }
00852 else
00853 {
00854 udelay = mdelay * 1000;
00855 }
00856
00857
00858 g_timeout.tv_sec = udelay / G_USEC_PER_SEC;
00859 g_timeout.tv_usec = udelay % G_USEC_PER_SEC;
00860
00861 DMPPRINTF("set delay %ld.%03d [was 0.%03d] (rule: %s)", g_timeout.tv_sec, g_timeout.tv_usec/1000, prev_delay, rule);
00862 }
00863
00864
00865 static void display_update(gint waveform)
00866 {
00867 DisplayUpdateInfo displayUpdateInfo;
00868
00869 displayUpdateInfo.color = 0;
00870 displayUpdateInfo.waveform = waveform;
00871
00872 #if DMLOGGING_ON
00873 GTimeVal curtime;
00874 g_get_current_time(&curtime);
00875
00876 DMPPRINTF("\n\n%ld:%3ld update waveform %d\n",
00877 curtime.tv_sec, curtime.tv_usec / 1000,
00878 displayUpdateInfo.waveform);
00879 #endif
00880
00881
00882 if (!g_vcom_is_set)
00883 {
00884 display_set_vcom(sys_get_display_vcom());
00885 g_vcom_is_set = TRUE;
00886 }
00887
00888
00889 delta_update_display(&displayUpdateInfo);
00890
00891
00892 sys_reset_idle_time();
00893 }
00894
00895
00896 static void on_message_timeout(void)
00897 {
00898 gint waveform = WAVEFORM_FULL;
00899
00900 if (useSpecialWaveform != 0)
00901 {
00902 waveform = useSpecialWaveform;
00903 }
00904
00905
00906 deltaAvailableAgain = getCurrentTime();
00907 if ((waveform == WAVEFORM_FULL) || (waveform == WAVEFORM_PARTIAL))
00908 {
00909 deltaAvailableAgain += DELTA_TIME_FULL;
00910 }
00911 else if (waveform == WAVEFORM_QUICK)
00912 {
00913 deltaAvailableAgain += DELTA_TIME_QUICK;
00914 }
00915
00916
00917 bzero(&DisplayCommand, sizeof(DMCommand));
00918 useSpecialWaveform = 0;
00919
00920
00921 display_update(waveform);
00922
00923 g_timeout.tv_sec = -1;
00924 g_timeout.tv_usec = -1;
00925 }
00926
00927
00928 static int delta_uploadwave(char *filename, glong offset)
00929 {
00930 LOGPRINTF("entry");
00931
00932 int ret = 0;
00933 FILE *file = NULL;
00934 WaveInfo info;
00935
00936
00937 file = fopen(filename, "rb");
00938 if (file == NULL)
00939 {
00940 ERRORPRINTF("Error opening file %s", filename);
00941 return -1;
00942 }
00943
00944 if (offset > 0)
00945 {
00946 if (fseek(file, offset, SEEK_SET) != 0)
00947 {
00948 ERRORPRINTF("Error seeking file in %s [%d]", filename, errno);
00949 return -1;
00950 }
00951 }
00952
00953 info.wave = malloc(WAVEFORM_SIZE);
00954 if (info.wave == NULL)
00955 {
00956 ERRORPRINTF("Not enough memory\n");
00957 return -1;
00958 }
00959
00960 info.size = fread(info.wave, 1, WAVEFORM_SIZE, file);
00961
00962
00963 fclose(file);
00964
00965 ret = ioctl(fbDev, FBIO_DELTA_UPLOADWAVES, &info);
00966 if (ret != 0)
00967 {
00968 ERRORPRINTF("Error sending FBIO_DELTA_UPLOADWAVES: %x", ret);
00969 }
00970
00971 free(info.wave);
00972
00973 return ret;
00974 }
00975
00976
00977 static void delta_init()
00978 {
00979 LOGPRINTF("entry");
00980
00981 gint ret = 0;
00982
00983 if ((ret = ioctl(fbDev, FBIO_DELTA_INIT, NULL)))
00984 {
00985 ERRORPRINTF("Error sending FBIO_DELTA_INIT: %x\n", ret);
00986 }
00987 }
00988
00989
00990 static gint delta_vcom_set(gfloat vcom)
00991 {
00992 LOGPRINTF("entry");
00993
00994 glong vcom_int = 0;
00995 gint ret = 0;
00996
00997 if(vcom < -5)
00998 {
00999 vcom = -5;
01000 }
01001 else if(vcom > 5)
01002 {
01003 vcom = 5;
01004 }
01005
01006 vcom_int = (signed long)(1000 * vcom);
01007
01008 if ((ret=ioctl(fbDev, FBIO_DETA_VCOM_SET, &vcom_int)))
01009 {
01010 ERRORPRINTF("Error sending FBIO_DETA_VCOM_SET: %x",ret);
01011 }
01012
01013 return ret;
01014 }
01015
01016
01017 static gint delta_erase(gint color)
01018 {
01019 LOGPRINTF("entry");
01020
01021 DisplayUpdateInfo updateinfo;
01022
01023 updateinfo.waveform = 0;
01024 updateinfo.color = color;
01025
01026 color = ((color & 0xf) << 4) + color;
01027
01028 int ret = ioctl(fbDev, FBIO_DELTA_ERASE, &updateinfo);
01029 if (ret != 0)
01030 {
01031 ERRORPRINTF("Error sending FBIO_DELTA_ERASE: %x",ret);
01032 }
01033 return ret;
01034 }
01035
01036
01037 static gint delta_busy(gint xpos, gint ypos, gint speed)
01038 {
01039 LOGPRINTF("entry");
01040
01041 BusyInfo info;
01042
01043 info.x = (unsigned short) xpos;
01044 info.y = (unsigned short) ypos;
01045 info.delay = (unsigned short) speed;
01046
01047 int ret = ioctl(fbDev, FBIO_DELTA_BUSY, &info);
01048 if (ret != 0)
01049 {
01050 ERRORPRINTF("Error sending FBIO_DELTA_BUSY: %x",ret);
01051 }
01052 return ret;
01053 }
01054
01055
01056 static gint delta_update_display(DisplayUpdateInfo *displayUpdateInfo)
01057 {
01058
01059
01060 int ret = ioctl(fbDev, FBIO_DELTA_UPDATE_DISPLAY, displayUpdateInfo);
01061 if (ret != 0)
01062 {
01063 ERRORPRINTF("Error sending FBIO_DELTA_UPDATE_DISPLAY: %x", ret);
01064 }
01065 return ret;
01066 }
01067
01068
01069 static gint parse_message(char *szCommand, erDmCmd_t * pCmd)
01070 {
01071 int i;
01072 char *pChar;
01073 char szToken[DM_MAXCHARONLINE];
01074
01075 pCmd->cc = (int) DM_UNDEFINED;
01076 for (i = 0; i < DM_N_ARG; i++)
01077 {
01078 strcpy(pCmd->arg[i], "");
01079 }
01080
01081
01082 if (szCommand[0] != '!')
01083 {
01084 ERRORPRINTF("Command should start with \'!\'. (%s)", szCommand);
01085 return -1;
01086 }
01087
01088
01089 pChar = szCommand + 1;
01090 i = 0;
01091 while (*pChar != '\0')
01092 {
01093 szToken[i] = '\0';
01094 if (*pChar == ',')
01095 {
01096 pChar++;
01097 break;
01098 }
01099 szToken[i] = *pChar++;
01100 i++;
01101 szToken[i] = '\0';
01102 }
01103
01104
01105 if (!strcmp(szToken, "I"))
01106 {
01107 strcpy(pCmd->name, szToken);
01108 pCmd->cc = DM_INFO;
01109 pCmd->nArg = 10;
01110 }
01111 else if (!strcmp(szToken, "F"))
01112 {
01113 strcpy(pCmd->name, szToken);
01114 pCmd->cc = DM_FORCE;
01115 pCmd->nArg = 3;
01116 }
01117 else
01118 {
01119 return -1;
01120 }
01121
01122 if (pCmd->nArg > 0)
01123 {
01124 get_arguments(pChar, pCmd, pCmd->nArg);
01125 }
01126 return 0;
01127 }
01128
01129
01130 static gint parse_command(erDmCmd_t *pCmd, DMCommand *command)
01131 {
01132 switch (pCmd->cc)
01133 {
01134 case DM_INFO:
01135 command->cmd = DM_INFO;
01136 command->info.pid = atoi(pCmd->arg[0]);
01137 command->info.x = atoi(pCmd->arg[1]);
01138 command->info.y = atoi(pCmd->arg[2]);
01139 command->info.w = atoi(pCmd->arg[3]);
01140 command->info.h = atoi(pCmd->arg[4]);
01141 command->info.shouldIgnore = atoi(pCmd->arg[5]);
01142 command->info.isWindow = atoi(pCmd->arg[6]);
01143 command->info.windowType = atoi(pCmd->arg[7]);
01144 strcpy(command->info.widgetType,pCmd->arg[8]);
01145 command->info.isFocus = atoi(pCmd->arg[9]);
01146 break;
01147
01148 case DM_FORCE:
01149 command->cmd = DM_FORCE;
01150 command->force.pid = atoi(pCmd->arg[0]);
01151 command->force.takeControl = atoi(pCmd->arg[1]);
01152 command->force.hint = atoi(pCmd->arg[2]);
01153 break;
01154
01155 default:
01156 ERRORPRINTF("Undefined command");
01157 return -1;
01158 break;
01159 }
01160 return 0;
01161 }
01162
01163
01164 static void get_arguments(char *pChar, erDmCmd_t * pCmd, int nReqArgs)
01165 {
01166 int nArg;
01167 int i;
01168 char szToken[DM_MAXCHARONLINE];
01169
01170 for (nArg = 0; nArg < nReqArgs; nArg++)
01171 {
01172 i = 0;
01173 while (*pChar != '\0')
01174 {
01175 szToken[i] = '\0';
01176 if (*pChar == ',')
01177 {
01178 pChar++;
01179 break;
01180 }
01181 szToken[i] = *pChar++;
01182 i++;
01183 szToken[i] = '\0';
01184 }
01185 strcpy(pCmd->arg[nArg], szToken);
01186 }
01187 }
01188
01189
01190 void display_set_ctb_window(gint wid)
01191 {
01192 g_ctb_window = wid;
01193 }
01194
01195
01196 static void *gtk_messages(void *arg)
01197 {
01198 int sockfd = -1;
01199 int error = 0;
01200 struct sockaddr_in server_addr;
01201 DMCommand command;
01202 erDmCmd_t cmd;
01203 gchar buffer[BUFFERSIZE];
01204 gsize n;
01205
01206
01207 fbDev = open("/dev/fb0", O_RDWR);
01208 if (fbDev == -1)
01209 {
01210 ERRORPRINTF("Cannot open framebufferdevice. # mknod /dev/fb0 c 29 0");
01211 return NULL;
01212 }
01213
01214
01215
01216 sockfd = socket(PF_INET, SOCK_DGRAM, 0);
01217 bzero(&server_addr, sizeof(struct sockaddr_in));
01218 server_addr.sin_family = AF_INET;
01219 server_addr.sin_port = htons(DMPORT);
01220 server_addr.sin_addr.s_addr = htonl(LOCALHOST);
01221 memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero));
01222
01223 bzero(&DisplayCommand, sizeof(DMCommand));
01224
01225 error = bind(sockfd, &server_addr, sizeof(server_addr));
01226 if (error)
01227 {
01228 perror("Error invoking bind");
01229 return NULL;
01230 }
01231
01232 int retval;
01233 fd_set rfds;
01234
01235
01236
01237 for (;;)
01238 {
01239 FD_ZERO(&rfds);
01240 FD_SET(sockfd, &rfds);
01241
01242 if (g_timeout.tv_sec > 0 || g_timeout.tv_usec > 0)
01243 {
01244
01245 retval = select(sockfd+1, &rfds, NULL, NULL, &g_timeout);
01246 }
01247 else
01248 {
01249
01250 retval = select(sockfd+1, &rfds, NULL, NULL, NULL);
01251 }
01252
01253 if (retval == -1 && errno == EINTR)
01254 {
01255 continue;
01256 }
01257 if (retval < 0)
01258 {
01259 ERRORPRINTF("error in select");
01260 return arg;
01261 }
01262 if (retval > 0)
01263 {
01264 if (FD_ISSET(sockfd, &rfds))
01265 {
01266
01267 recv(sockfd, buffer, BUFFERSIZE, MSG_PEEK);
01268 gint state = sys_get_power_state();
01269 if ((state == STATE_POWER_IDLE) || (state == STATE_POWER_STANDBY))
01270 {
01271
01272 g_usleep(10*1000);
01273 continue;
01274 }
01275
01276 n = recv(sockfd, buffer, BUFFERSIZE, 0);
01277 buffer[n] = '\0';
01278 parse_gtk_message(buffer);
01279 }
01280 else
01281 {
01282 WARNPRINTF("huh? data for other channel");
01283 }
01284 }
01285 else
01286 {
01287 if (g_timeout.tv_sec >= 0 || g_timeout.tv_usec >= 0)
01288 {
01289
01290 on_message_timeout();
01291 }
01292 else
01293 {
01294
01295 }
01296 }
01297 }
01298 return arg;
01299 }