window.c (16521B)
1 2 #include <Elementary.h> 3 #include <EWebKit2.h> 4 5 #include "viking_state.h" 6 #include "viking.h" 7 #include "utilities.h" 8 #include "commands.h" 9 #include "window.h" 10 #include "keymap.h" 11 12 13 static Eina_Bool commandhistoryfetch(const Arg *, void *); 14 15 static void 16 inputbox_activate_cb(void *data, Evas_Object *obj, void *event_info) 17 { 18 const char *text; 19 Window_Data *wd = data; 20 // App_Data *ad = wd->app; 21 uint16_t length = strlen(elm_entry_entry_get(wd->url)); 22 Arg a; 23 Eina_Bool forward = EINA_FALSE; 24 25 // printf("In inputbox_activate\n"); 26 27 a.i = HideCompletion; 28 complete(&a, data); 29 if (length == 0) 30 return; 31 text = elm_entry_entry_get(wd->url); 32 if (length > 1 && text[0] == ':') { 33 process_line((text + 1), data); 34 } else if (length > 1 && ((forward = text[0] == '/') || text[0] == '?')) { 35 ewk_view_text_find_highlight_clear(wd->cur_buf->view); 36 37 ewk_view_text_find(wd->cur_buf->view, &text[1], 38 EWK_FIND_OPTIONS_SHOW_HIGHLIGHT | EWK_FIND_OPTIONS_CASE_INSENSITIVE, 1000); 39 40 wd->count = 0; 41 wd->search_direction = forward; 42 wd->search_handle = strdup(&text[1]); 43 } else if (text[0] == '.' || text[0] == ',' || text[0] == ';') { 44 a.i = Silent; 45 a.s = strdup("hints.fire();"); 46 script(&a, data); 47 free(a.s); 48 gui_scroll_update(wd); 49 } else 50 return; 51 if (!wd->echo_active) 52 // gtk_entry_set_text(entry, ""); 53 elm_entry_entry_set(wd->url, ""); 54 // gtk_widget_grab_focus(GTK_WIDGET(webview)); 55 56 /* process_line above may have deleted the tab, check if its still around */ 57 if (wd->cur_buf->view) { 58 // elm_object_focus_set(elm_object_top_widget_get(wd->win), EINA_FALSE); 59 evas_object_focus_set(wd->cur_buf->view, EINA_TRUE); 60 } 61 } 62 63 static Eina_Bool 64 commandhistoryfetch(const Arg *arg, void *data) 65 { 66 Window_Data *wd = data; 67 // App_Data *ad = wd->app; 68 char *command; 69 const int length = eina_list_count(wd->commandhistory); 70 71 if (length > 0) { 72 if (arg->i == DirectionPrev) { 73 wd->commandpointer = (length + wd->commandpointer - 1) % length; 74 } else { 75 wd->commandpointer = (length + wd->commandpointer + 1) % length; 76 } 77 78 command = eina_list_nth(wd->commandhistory, wd->commandpointer); 79 // gtk_entry_set_text(GTK_ENTRY(inputbox), g_strconcat(":", command, NULL)); 80 // gtk_editable_set_position(GTK_EDITABLE(inputbox), -1); 81 command = strdup_printf(":%s", command); 82 elm_entry_entry_set(wd->url, command); 83 free(command); 84 elm_entry_cursor_line_end_set(wd->url); 85 return EINA_TRUE; 86 } 87 88 return EINA_FALSE; 89 } 90 91 static void 92 inputbox_keypress_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) 93 { 94 Arg a; 95 int numval; 96 Evas_Event_Key_Down *ev = event_info; 97 Window_Data *wd = data; 98 // App_Data *ad = wd->app; 99 100 if (wd->mode == ModeHints) { 101 // if (event->keyval == GDK_ISO_Left_Tab) { 102 if (!strcmp(ev->keyname, "Tab") && evas_key_modifier_is_set(ev->modifiers, "Shift")) { 103 a.i = Silent; 104 a.s = strdup("hints.focusPreviousHint();"); 105 script(&a, data); 106 free(a.s); 107 gui_scroll_update(wd); 108 return; 109 } 110 // if (event->keyval == GDK_Tab) { 111 if (!strcmp(ev->keyname, "Tab")) { 112 a.i = Silent; 113 a.s = strdup("hints.focusNextHint();"); 114 script(&a, data); 115 free(a.s); 116 gui_scroll_update(wd); 117 return; 118 } 119 // if (event->keyval == GDK_Return) { 120 if (!strcmp(ev->keyname, "Return")) { 121 a.i = Silent; 122 a.s = strdup_printf("hints.fire();"); 123 script(&a, data); 124 free(a.s); 125 gui_scroll_update(wd); 126 return; 127 } 128 } 129 if (!strcmp(ev->keyname, "[") || !strcmp(ev->keyname, "Escape")) { 130 a.i = HideCompletion; 131 complete(&a, data); 132 a.i = ModeNormal; 133 wd->commandpointer = 0; 134 set(&a, data); 135 return; 136 } 137 else if (!strcmp(ev->keyname, "Tab") && evas_key_modifier_is_set(ev->modifiers, "Shift")) { 138 a.i = DirectionPrev; 139 complete(&a, data); 140 return; 141 } 142 else if (!strcmp(ev->keyname, "Tab")) { 143 a.i = DirectionNext; 144 complete(&a, data); 145 return; 146 } 147 else if (!strcmp(ev->keyname, "Up")) { 148 a.i = DirectionPrev; 149 commandhistoryfetch(&a, data); 150 return; 151 } 152 else if (!strcmp(ev->keyname, "Down")) { 153 a.i = DirectionNext; 154 commandhistoryfetch(&a, data); 155 return; 156 } 157 158 /* 159 switch (event->keyval) { 160 case GDK_bracketleft: 161 case GDK_Escape: 162 if (!IS_ESCAPE(event)) break; 163 a.i = HideCompletion; 164 complete(&a, data); 165 a.i = ModeNormal; 166 commandpointer = 0; 167 return set(&a, ad); 168 break; 169 case GDK_Tab: 170 a.i = DirectionNext; 171 return complete(&a, data); 172 break; 173 case GDK_Up: 174 a.i = DirectionPrev; 175 return commandhistoryfetch(&a); 176 break; 177 case GDK_Down: 178 a.i = DirectionNext; 179 return commandhistoryfetch(&a); 180 break; 181 case GDK_ISO_Left_Tab: 182 a.i = DirectionPrev; 183 return complete(&a, data); 184 break; 185 } 186 */ 187 188 if (wd->mode == ModeHints) { 189 #if 0 190 if ((CLEAN(event->state) & GDK_SHIFT_MASK) && 191 (CLEAN(event->state) & GDK_CONTROL_MASK) && 192 (event->keyval == GDK_BackSpace)) { 193 count /= 10; 194 a.i = Silent; 195 a.s = g_strdup_printf("hints.updateHints(%d);", count); 196 script(&a, data); 197 g_free(a.s); 198 update_state(); 199 return TRUE; 200 } 201 #endif 202 203 // numval = g_unichar_digit_value((gunichar) gdk_keyval_to_unicode(event->keyval)); 204 numval = atoi(ev->key); 205 if ((numval >= 1 && numval <= 9) || (numval == 0 && wd->count)) { 206 /* allow a zero as non-first number */ 207 wd->count = (wd->count ? wd->count * 10 : 0) + numval; 208 a.i = Silent; 209 a.s = strdup_printf("hints.updateHints(%d);", wd->count); 210 script(&a, data); 211 free(a.s); 212 gui_count_update(wd); 213 return; 214 } 215 } 216 } 217 218 static void 219 inputbox_keyrelease_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) 220 { 221 Arg a; 222 Window_Data *wd = data; 223 // guint16 length = gtk_entry_get_text_length(entry); 224 uint16_t length = strlen(elm_entry_entry_get(wd->url)); 225 226 if (!length) { 227 a.i = HideCompletion; 228 complete(&a, data); 229 a.i = ModeNormal; 230 set(&a, data); 231 } 232 } 233 234 /* used for incremental search */ 235 static void 236 inputbox_changed_cb(void *data, Evas_Object *obj, void *event_info) 237 { 238 Arg a; 239 Window_Data *wd = data; 240 const char *text = elm_entry_entry_get(wd->url); 241 uint16_t length = strlen(text); 242 Eina_Bool forward = EINA_FALSE; 243 244 /* Update incremental search if the user changes the search text. 245 * 246 * Note: gtk_widget_is_focus() is a poor way to check if the change comes 247 * from the user. But if the entry is focused and the text is set 248 * through gtk_entry_set_text() in some asyncrounous operation, 249 * I would consider that a bug. 250 */ 251 252 if (elm_object_focus_get(wd->url) && length > 1 && ((forward = text[0] == '/') || text[0] == '?')) { 253 ewk_view_text_find_highlight_clear(wd->cur_buf->view); 254 ewk_view_text_find(wd->cur_buf->view, &text[1], 255 EWK_FIND_OPTIONS_SHOW_HIGHLIGHT | EWK_FIND_OPTIONS_CASE_INSENSITIVE, 1000); 256 return; 257 } else if (elm_object_focus_get(wd->url) && length >= 1 && 258 (text[0] == '.' || text[0] == ',' || text[0] == ';')) { 259 a.i = Silent; 260 switch (text[0]) { 261 case '.': 262 a.s = strdup_printf("hints.createHints('%s', 'f');", text + 1); 263 break; 264 265 case ',': 266 a.s = strdup_printf("hints.createHints('%s', 'F');", text + 1); 267 break; 268 269 case ';': 270 a.s = NULL; 271 switch (text[1]) { 272 case 's': 273 a.s = strdup_printf("hints.createHints('%s', 's');", text + 2); 274 break; 275 case 'y': 276 a.s = strdup_printf("hints.createHints('%s', 'y');", text + 2); 277 break; 278 case 'o': 279 a.s = strdup_printf("hints.createHints('%s', 'f');", text + 2); 280 break; 281 case 't': case 'w': 282 a.s = strdup_printf("hints.createHints('%s', 'F');", text + 2); 283 break; 284 case 'O': case 'T': case 'W': 285 a.s = strdup_printf("hints.createHints('%s', 'O');", text + 2); 286 break; 287 case 'i': 288 a.s = strdup_printf("hints.createHints('%s', 'i');", text + 2); 289 break; 290 case 'I': 291 a.s = strdup_printf("hints.createHints('%s', 'I');", text + 2); 292 break; 293 } 294 break; 295 } 296 wd->count = 0; 297 if (a.s) { 298 script(&a, data); 299 free(a.s); 300 } 301 302 return; 303 } else if (length == 0 && wd->followTarget[0]) { 304 wd->mode = ModeNormal; 305 a.i = Silent; 306 a.s = strdup("hints.clearHints();"); 307 script(&a, data); 308 free(a.s); 309 wd->count = 0; 310 gui_count_update(wd); 311 } 312 } 313 314 static void 315 delete_request_cb(void *data, Evas_Object *obj, void *event_info) 316 { 317 Window_Data *wd = data; 318 319 printf("window requested deletion .."); 320 321 if (eina_list_count(wd->buffer_list) > 1) { 322 printf("denied, more than 1 buffer open\n"); 323 } 324 else { 325 printf("ok!\n"); 326 evas_object_del(wd->win); 327 } 328 } 329 330 static void 331 free_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) 332 { 333 Window_Data *wd = data; 334 App_Data *ad = wd->app; 335 336 session_windows_del(ad->session, wd->session_window); 337 session_window_free(wd->session_window); 338 339 ad->windows = eina_list_remove(ad->windows, wd); 340 341 eina_list_free(wd->buffer_list); 342 eina_list_free(wd->commandhistory); 343 free(wd); 344 printf("window_free_cb()\n"); 345 } 346 347 static void 348 maximized_cb(void *data, Evas_Object *obj, void *event_info) 349 { 350 printf("browser window maximized\n"); 351 } 352 353 void 354 window_main_buffer_set(Buffer_Data *new_buf) 355 { 356 Window_Data *wd = new_buf->window; 357 Buffer_Data *old_buf = wd->cur_buf; 358 App_Data *ad = wd->app; 359 360 if (new_buf == old_buf || ad->exiting) 361 return; 362 363 if (old_buf) { 364 elm_box_unpack_all(wd->webkit_box); 365 evas_object_hide(old_buf->view); 366 367 // if (old_buf->inspector_enabled) 368 // ewk_view_web_inspector_close(old_buf->view); 369 } 370 371 wd->cur_buf = new_buf; 372 373 if (new_buf) { 374 elm_box_pack_end(wd->webkit_box, new_buf->view); 375 evas_object_show(new_buf->view); 376 377 //if (new_buf->inspector_enabled) { 378 // ewk_view_web_inspector_show(new_buf->view); 379 //} 380 381 /* left side */ 382 make_buffer_number(wd->status_buffer_num, new_buf); 383 make_favicon(wd->status_favicon, new_buf); 384 make_url(wd->status_url, new_buf); 385 make_bf_list(wd->status_back_forward, new_buf); 386 387 /* right side */ 388 gui_count_update(wd); 389 gui_modkey_update(wd); 390 gui_zoom_update(wd, ewk_view_scale_get(new_buf->view)); 391 gui_scroll_update(wd); 392 } 393 } 394 395 Window_Data* 396 window_add(App_Data *ad, Session_Window *session_window) 397 { 398 Window_Data *wd; 399 Evas_Modifier_Mask mask; 400 Evas *e; 401 unsigned int i; 402 403 wd = calloc(1, sizeof(Window_Data)); 404 if (!wd) return NULL; 405 406 Evas_Object *win, *bg, *box, *status_bar, *url, *webkit_box, *status_url; 407 Evas_Object *event_box, *web_inspector, *progress, *downloads; 408 Evas_Object *status_back_forward, *status_buffer_num, *status_favicon; 409 Evas_Object *status_count, *status_modkey, *status_zoom, *status_scroll; 410 411 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); 412 413 win = elm_win_add(NULL, "viking", ELM_WIN_BASIC); 414 //elm_win_screen_constrain_set(win, EINA_TRUE); 415 //elm_win_keyboard_mode_set(win, ELM_WIN_KEYBOARD_ON); 416 417 e = evas_object_evas_get(win); 418 for (i = 0; i < LENGTH(keys); i++) { 419 mask = evas_key_modifier_mask_get(e, keys[i].mask); 420 if (keys[i].key && !evas_object_key_grab(win, keys[i].key, mask, 0, EINA_FALSE)) 421 fprintf(stderr, "grab failed mask = %s, key = %s\n", keys[i].mask , keys[i].key); 422 } 423 424 /* program bacground */ 425 bg = elm_bg_add(win); 426 evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); 427 elm_win_resize_object_add(win, bg); 428 // elm_bg_color_set(bg, 0, 0, 0); 429 evas_object_layer_set(bg, EVAS_LAYER_MIN); 430 evas_object_show(bg); 431 432 /* main box that everything goes into, resizes with window */ 433 box = elm_box_add(win); 434 evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); 435 elm_win_resize_object_add(win, box); 436 evas_object_show(box); 437 438 /* box that shows the web view */ 439 webkit_box = elm_box_add(win); 440 evas_object_size_hint_weight_set(webkit_box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); 441 evas_object_size_hint_align_set(webkit_box, EVAS_HINT_FILL, EVAS_HINT_FILL); 442 elm_box_pack_end(box, webkit_box); 443 evas_object_show(webkit_box); 444 445 /* status bar container */ 446 status_bar = elm_box_add(win); 447 elm_box_horizontal_set(status_bar, EINA_TRUE); 448 evas_object_size_hint_align_set(status_bar, EVAS_HINT_FILL, EVAS_HINT_FILL); 449 elm_box_pack_end(box, status_bar); 450 evas_object_show(status_bar); 451 452 /* status buffer number */ 453 status_buffer_num = elm_label_add(win); 454 elm_box_pack_end(status_bar, status_buffer_num); 455 evas_object_show(status_buffer_num); 456 457 /* status favicon */ 458 status_favicon = elm_box_add(win); 459 elm_box_pack_end(status_bar, status_favicon); 460 evas_object_show(status_favicon); 461 462 /* status current url */ 463 status_url = elm_label_add(win); 464 elm_box_pack_end(status_bar, status_url); 465 evas_object_show(status_url); 466 467 /* status able to go back/forward indicator */ 468 status_back_forward = elm_label_add(win); 469 evas_object_size_hint_weight_set(status_back_forward, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); 470 evas_object_size_hint_align_set(status_back_forward, 0.0, EVAS_HINT_FILL); 471 elm_box_pack_end(status_bar, status_back_forward); 472 evas_object_show(status_back_forward); 473 474 /* status number of downloads */ 475 downloads = elm_label_add(win); 476 evas_object_size_hint_align_set(downloads, 1.0, EVAS_HINT_FILL); 477 elm_box_pack_end(status_bar, downloads); 478 evas_object_show(downloads); 479 480 /* current "count" */ 481 status_count = elm_label_add(win); 482 evas_object_size_hint_align_set(status_count, 1.0, EVAS_HINT_FILL); 483 elm_box_pack_end(status_bar, status_count); 484 evas_object_show(status_count); 485 486 /* current modkey */ 487 status_modkey = elm_label_add(win); 488 evas_object_size_hint_align_set(status_modkey, 1.0, EVAS_HINT_FILL); 489 elm_box_pack_end(status_bar, status_modkey); 490 evas_object_show(status_modkey); 491 492 /* current zoom level */ 493 status_zoom = elm_label_add(win); 494 evas_object_size_hint_align_set(status_zoom, 1.0, EVAS_HINT_FILL); 495 elm_box_pack_end(status_bar, status_zoom); 496 evas_object_show(status_zoom); 497 498 /* status current progress bar */ 499 progress = elm_progressbar_add(win); 500 elm_progressbar_horizontal_set(progress, EINA_TRUE); 501 evas_object_size_hint_align_set(progress, 0.0, 1.0); 502 elm_progressbar_unit_format_set(progress, NULL); 503 evas_object_size_hint_min_set(progress, 100, 11); 504 evas_object_size_hint_max_set(progress, 100, 11); 505 elm_box_pack_end(status_bar, progress); 506 evas_object_show(progress); 507 508 /* scroll position */ 509 status_scroll = elm_label_add(win); 510 evas_object_size_hint_align_set(status_scroll, 1.0, EVAS_HINT_FILL); 511 elm_box_pack_end(status_bar, status_scroll); 512 evas_object_show(status_scroll); 513 514 /* invisible until activated web inspector */ 515 web_inspector = elm_box_add(win); 516 evas_object_size_hint_align_set(web_inspector, EVAS_HINT_FILL, EVAS_HINT_FILL); 517 elm_box_pack_end(box, web_inspector); 518 evas_object_hide(web_inspector); 519 520 /* invisible event box, populated on tab completions and :ls */ 521 event_box = elm_box_add(win); 522 evas_object_size_hint_align_set(event_box, EVAS_HINT_FILL, EVAS_HINT_FILL); 523 elm_box_pack_end(box, event_box); 524 evas_object_hide(event_box); 525 526 /* main entry widget */ 527 url = elm_entry_add(win); 528 elm_entry_single_line_set(url, EINA_TRUE); 529 elm_entry_scrollable_set(url, EINA_TRUE); 530 evas_object_size_hint_weight_set(url, EVAS_HINT_EXPAND, 0.0); 531 evas_object_size_hint_align_set(url, EVAS_HINT_FILL, EVAS_HINT_FILL); 532 elm_box_pack_end(box, url); 533 elm_entry_text_style_user_push(url, "DEFAULT='font=Monospace font_size=12'"); 534 evas_object_show(url); 535 536 wd->win = win; 537 wd->bg = bg; 538 wd->main_box = box; 539 wd->webkit_box = webkit_box; 540 wd->url = url; 541 wd->status_buffer_num = status_buffer_num; 542 wd->status_favicon = status_favicon; 543 wd->status_url = status_url; 544 wd->status_back_forward = status_back_forward; 545 wd->status_count = status_count; 546 wd->status_modkey = status_modkey; 547 wd->status_zoom = status_zoom; 548 wd->progress_bar = progress; 549 wd->status_scroll = status_scroll; 550 wd->event_box = event_box; 551 wd->web_inspector = web_inspector; 552 wd->downloads = downloads; 553 wd->app = ad; 554 wd->mode = ModeNormal; 555 wd->echo_active = EINA_FALSE; 556 557 if (session_window) { 558 wd->session_window = session_window; 559 } 560 else { 561 wd->session_window = session_window_new(NULL, EINA_FALSE); 562 session_windows_add(ad->session, wd->session_window); 563 } 564 565 evas_object_smart_callback_add(wd->win, "delete,request", delete_request_cb, wd); 566 evas_object_smart_callback_add(wd->win, "maximized", maximized_cb, wd); 567 evas_object_event_callback_add(wd->win, EVAS_CALLBACK_FREE, free_cb, wd); 568 569 evas_object_smart_callback_add(wd->url, "activated", inputbox_activate_cb, wd); 570 evas_object_smart_callback_add(wd->url, "changed", inputbox_changed_cb, wd); 571 evas_object_event_callback_add(wd->url, EVAS_CALLBACK_KEY_DOWN, inputbox_keypress_cb, wd); 572 evas_object_event_callback_add(wd->url, EVAS_CALLBACK_KEY_UP, inputbox_keyrelease_cb, wd); 573 574 ad->windows = eina_list_append(ad->windows, wd); 575 576 evas_object_resize(wd->win, 1024, 768); 577 evas_object_show(wd->win); 578 579 return wd; 580 } 581