| /* | |
| Copyright 2007-2010 WebDriver committers | |
| Copyright 2007-2010 Google Inc. | |
| Licensed under the Apache License, Version 2.0 (the "License"); | |
| you may not use this file except in compliance with the License. | |
| You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software | |
| distributed under the License is distributed on an "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| See the License for the specific language governing permissions and | |
| limitations under the License. | |
| */ | |
| #include <ctime> | |
| #include <string> | |
| #include <iostream> | |
| #include <fstream> | |
| #include "interactions.h" | |
| #include "logging.h" | |
| #include <gdk/gdk.h> | |
| #include <gdk/gdkkeysyms.h> | |
| #include <X11/Xlib.h> | |
| #include <time.h> | |
| #include <stdlib.h> | |
| #include <assert.h> | |
| #include <list> | |
| #include <algorithm> | |
| #include <functional> | |
| #include "translate_keycode_linux.h" | |
| #include "interactions_linux.h" | |
| using namespace std; | |
| guint32 gLatestEventTime = 0; | |
| // This is the timestamp needed in the GDK events. | |
| guint32 TimeSinceBootMsec() | |
| { | |
| struct timespec clk_tm; | |
| const int msec_nsec_factor = 1000000; | |
| const int sec_msec_factor = 1000; | |
| int clk_ret = clock_gettime(CLOCK_MONOTONIC, &clk_tm); | |
| if (clk_ret == 0) | |
| { | |
| return (clk_tm.tv_sec * sec_msec_factor + | |
| (clk_tm.tv_nsec / msec_nsec_factor)); | |
| } | |
| return 0; | |
| } | |
| void sleep_for_ms(int sleep_time_ms) | |
| { | |
| struct timespec sleep_time; | |
| sleep_time.tv_sec = sleep_time_ms / 1000; | |
| sleep_time.tv_nsec = (sleep_time_ms % 1000) * 1000000; | |
| nanosleep(&sleep_time, NULL); | |
| } | |
| bool is_gdk_keyboard_event(GdkEvent* ev) | |
| { | |
| return ((ev->type == GDK_KEY_PRESS) || (ev->type == GDK_KEY_RELEASE)); | |
| } | |
| bool is_gdk_mouse_event(GdkEvent* ev) | |
| { | |
| return ((ev->type == GDK_BUTTON_PRESS) || (ev->type == GDK_BUTTON_RELEASE) || | |
| (ev->type == GDK_MOTION_NOTIFY) || (ev->type == GDK_2BUTTON_PRESS)); | |
| } | |
| bool event_earlier_than(GdkEvent* ev, guint32 compare_time) | |
| { | |
| assert(is_gdk_keyboard_event(ev) || is_gdk_mouse_event(ev)); | |
| return (ev->key.time <= compare_time); | |
| } | |
| void print_key_event(GdkEvent* p_ev) | |
| { | |
| if (!((p_ev->type == GDK_KEY_PRESS) || (p_ev->type == GDK_KEY_RELEASE))) { | |
| LOG(DEBUG) << "Not a key event."; | |
| return; | |
| } | |
| const gchar* gdk_name = gdk_keyval_name(p_ev->key.keyval); | |
| const char* kNameUnknown = "UNKNOWN"; | |
| const char* print_name = (gdk_name != NULL ? gdk_name : kNameUnknown); | |
| std::string ev_type = (p_ev->type == GDK_KEY_PRESS ? "press" : "release"); | |
| LOG(DEBUG) << "Type: " << ev_type << "Key code: " << p_ev->key.keyval << | |
| " (" << print_name << ") time: " << | |
| p_ev->key.time << " state: " << p_ev->key.state << " hw keycode: " | |
| << (int) p_ev->key.hardware_keycode << " "; | |
| } | |
| bool additional_events_to_wait_for(GdkEvent* p_event) | |
| { | |
| return ((p_event->type == GDK_LEAVE_NOTIFY) || | |
| (p_event->type == GDK_ENTER_NOTIFY)); | |
| } | |
| void init_logging() | |
| { | |
| #ifdef INTERACTIONS_DEBUG | |
| static bool log_initalized = false; | |
| if (!log_initalized) { | |
| LOG::Level("DEBUG"); | |
| LOG::File(INTERACTIONS_LOG_FILE, "a"); | |
| log_initalized = true; | |
| } | |
| #endif | |
| } | |
| extern "C" | |
| { | |
| bool pending_input_events() | |
| { | |
| LOG(DEBUG) << "Waiting for all events to be processed. Latest: " << gLatestEventTime; | |
| GdkEvent* lastEvent = gdk_event_peek(); | |
| LOG(DEBUG) << "Got event: " << | |
| (lastEvent != NULL ? lastEvent->type : 0); | |
| if ((lastEvent != NULL) && is_gdk_keyboard_event(lastEvent)) { | |
| print_key_event(lastEvent); | |
| } | |
| bool ret_val = false; | |
| if (lastEvent != NULL && | |
| (((is_gdk_keyboard_event(lastEvent) || is_gdk_mouse_event(lastEvent)) && | |
| event_earlier_than(lastEvent, gLatestEventTime)) | |
| || (additional_events_to_wait_for(lastEvent)))) { | |
| ret_val = true; | |
| } | |
| if (lastEvent != NULL) { | |
| gdk_event_free(lastEvent); | |
| } | |
| LOG(DEBUG) << "Returning: " << ret_val; | |
| return ret_val; | |
| } | |
| // Does nothing on Linux | |
| void stopPersistentEventFiring() | |
| { | |
| } | |
| void setEnablePersistentHover(bool enablePersistentHover) | |
| { | |
| } | |
| } |