X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fchromeos%2Fime%2Fxkeyboard.cc;h=a34413862bfa3ae535251437fb69ff9df42ee4dc;hb=ff3e2503a20db9193d323c1d19c38c68004dec4a;hp=ec8c32a97fbc82f3b8251aafcd4da1aa8c7fc6b9;hpb=7338fba38ba696536d1cc9d389afd716a6ab2fe6;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/chromeos/ime/xkeyboard.cc b/src/chromeos/ime/xkeyboard.cc index ec8c32a..a344138 100644 --- a/src/chromeos/ime/xkeyboard.cc +++ b/src/chromeos/ime/xkeyboard.cc @@ -10,9 +10,11 @@ #include #include +#include "base/bind.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" +#include "base/process/kill.h" #include "base/process/launch.h" #include "base/process/process_handle.h" #include "base/strings/string_util.h" @@ -23,7 +25,6 @@ // These includes conflict with base/tracked_objects.h so must come last. #include #include -#include namespace chromeos { namespace input_method { @@ -33,6 +34,10 @@ Display* GetXDisplay() { return base::MessagePumpForUI::GetDefaultXDisplay(); } +// The delay in milliseconds that we'll wait between checking if +// setxkbmap command finished. +const int kSetLayoutCommandCheckDelayMs = 100; + // The command we use to set the current XKB layout and modifier key mapping. // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) const char kSetxkbmapCommand[] = "/usr/bin/setxkbmap"; @@ -79,6 +84,8 @@ class XKeyboardImpl : public XKeyboard { virtual unsigned int GetNumLockMask() OVERRIDE; virtual void GetLockedModifiers(bool* out_caps_lock_enabled, bool* out_num_lock_enabled) OVERRIDE; + virtual bool SetAutoRepeatEnabled(bool enabled) OVERRIDE; + virtual bool SetAutoRepeatRate(const AutoRepeatRate& rate) OVERRIDE; private: // This function is used by SetLayout() and RemapModifierKeys(). Calls @@ -90,8 +97,11 @@ class XKeyboardImpl : public XKeyboard { // TODO(yusukes): Use libxkbfile.so instead of the command (crosbug.com/13105) void MaybeExecuteSetLayoutCommand(); + // Polls to see setxkbmap process exits. + void PollUntilChildFinish(const base::ProcessHandle handle); + // Called when execve'd setxkbmap process exits. - static void OnSetLayoutFinish(pid_t pid, int status, XKeyboardImpl* self); + void OnSetLayoutFinish(); const bool is_running_on_chrome_os_; unsigned int num_lock_mask_; @@ -107,11 +117,14 @@ class XKeyboardImpl : public XKeyboard { base::ThreadChecker thread_checker_; + base::WeakPtrFactory weak_factory_; + DISALLOW_COPY_AND_ASSIGN(XKeyboardImpl); }; XKeyboardImpl::XKeyboardImpl() - : is_running_on_chrome_os_(base::SysInfo::IsRunningOnChromeOS()) { + : is_running_on_chrome_os_(base::SysInfo::IsRunningOnChromeOS()), + weak_factory_(this) { // X must be already initialized. CHECK(GetXDisplay()); @@ -182,13 +195,41 @@ void XKeyboardImpl::MaybeExecuteSetLayoutCommand() { return; } - // g_child_watch_add is necessary to prevent the process from becoming a - // zombie. - const base::ProcessId pid = base::GetProcId(handle); - g_child_watch_add(pid, - reinterpret_cast(OnSetLayoutFinish), - this); - DVLOG(1) << "ExecuteSetLayoutCommand: " << layout_to_set << ": pid=" << pid; + PollUntilChildFinish(handle); + + DVLOG(1) << "ExecuteSetLayoutCommand: " + << layout_to_set << ": pid=" << base::GetProcId(handle); +} + +// Delay and loop until child process finishes and call the callback. +void XKeyboardImpl::PollUntilChildFinish(const base::ProcessHandle handle) { + int exit_code; + DVLOG(1) << "PollUntilChildFinish: poll for pid=" << base::GetProcId(handle); + switch (base::GetTerminationStatus(handle, &exit_code)) { + case base::TERMINATION_STATUS_STILL_RUNNING: + DVLOG(1) << "PollUntilChildFinish: Try waiting again"; + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&XKeyboardImpl::PollUntilChildFinish, + weak_factory_.GetWeakPtr(), handle), + base::TimeDelta::FromMilliseconds(kSetLayoutCommandCheckDelayMs)); + return; + + case base::TERMINATION_STATUS_NORMAL_TERMINATION: + DVLOG(1) << "PollUntilChildFinish: Child process finished"; + OnSetLayoutFinish(); + return; + + case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: + DVLOG(1) << "PollUntilChildFinish: Abnormal exit code: " << exit_code; + OnSetLayoutFinish(); + return; + + default: + NOTIMPLEMENTED(); + OnSetLayoutFinish(); + return; + } } bool XKeyboardImpl::NumLockIsEnabled() { @@ -258,6 +299,28 @@ void XKeyboardImpl::GetLockedModifiers(bool* out_caps_lock_enabled, *out_num_lock_enabled = status.locked_mods & num_lock_mask_; } +bool XKeyboardImpl::SetAutoRepeatEnabled(bool enabled) { + if (enabled) + XAutoRepeatOn(GetXDisplay()); + else + XAutoRepeatOff(GetXDisplay()); + DVLOG(1) << "Set auto-repeat mode to: " << (enabled ? "on" : "off"); + return true; +} + +bool XKeyboardImpl::SetAutoRepeatRate(const AutoRepeatRate& rate) { + DVLOG(1) << "Set auto-repeat rate to: " + << rate.initial_delay_in_ms << " ms delay, " + << rate.repeat_interval_in_ms << " ms interval"; + if (XkbSetAutoRepeatRate(GetXDisplay(), XkbUseCoreKbd, + rate.initial_delay_in_ms, + rate.repeat_interval_in_ms) != True) { + DVLOG(1) << "Failed to set auto-repeat rate"; + return false; + } + return true; +} + void XKeyboardImpl::SetLockedModifiers(ModifierLockStatus new_caps_lock_status, ModifierLockStatus new_num_lock_status) { DCHECK(thread_checker_.CalledOnValidThread()); @@ -315,47 +378,19 @@ void XKeyboardImpl::ReapplyCurrentModifierLockStatus() { current_num_lock_status_ ? kEnableLock : kDisableLock); } -// static -void XKeyboardImpl::OnSetLayoutFinish(pid_t pid, - int status, - XKeyboardImpl* self) { - DVLOG(1) << "OnSetLayoutFinish: pid=" << pid; - if (self->execute_queue_.empty()) { +void XKeyboardImpl::OnSetLayoutFinish() { + if (execute_queue_.empty()) { DVLOG(1) << "OnSetLayoutFinish: execute_queue_ is empty. " - << "base::LaunchProcess failed? pid=" << pid; + << "base::LaunchProcess failed?"; return; } - self->execute_queue_.pop(); - self->MaybeExecuteSetLayoutCommand(); + execute_queue_.pop(); + MaybeExecuteSetLayoutCommand(); } } // namespace // static -bool XKeyboard::SetAutoRepeatEnabled(bool enabled) { - if (enabled) - XAutoRepeatOn(GetXDisplay()); - else - XAutoRepeatOff(GetXDisplay()); - DVLOG(1) << "Set auto-repeat mode to: " << (enabled ? "on" : "off"); - return true; -} - -// static -bool XKeyboard::SetAutoRepeatRate(const AutoRepeatRate& rate) { - DVLOG(1) << "Set auto-repeat rate to: " - << rate.initial_delay_in_ms << " ms delay, " - << rate.repeat_interval_in_ms << " ms interval"; - if (XkbSetAutoRepeatRate(GetXDisplay(), XkbUseCoreKbd, - rate.initial_delay_in_ms, - rate.repeat_interval_in_ms) != True) { - DVLOG(1) << "Failed to set auto-repeat rate"; - return false; - } - return true; -} - -// static bool XKeyboard::GetAutoRepeatEnabledForTesting() { XKeyboardState state = {}; XGetKeyboardControl(GetXDisplay(), &state);