1777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* Copyright (C) 2010 The Android Open Source Project 2777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** 3777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** This software is licensed under the terms of the GNU General Public 4777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** License version 2, as published by the Free Software Foundation, and 5777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** may be copied, distributed, and modified under those terms. 6777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** 7777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** This program is distributed in the hope that it will be useful, 8777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** but WITHOUT ANY WARRANTY; without even the implied warranty of 9777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine** GNU General Public License for more details. 11777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine*/ 12777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 13777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* 14777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * Contains the Core-side implementation of the "core-ui-control" service that is 15777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * part of the UI control protocol. Here we send UI control commands to the UI. 16777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine */ 17777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 18777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/android.h" 19777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/hw-control.h" 20777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/looper.h" 21777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/async-utils.h" 22777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/sync-utils.h" 23777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/utils/debug.h" 24777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/protocol/ui-commands.h" 25777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/protocol/ui-commands-proxy.h" 26777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine#include "android/protocol/ui-commands-api.h" 27777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 28777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* Descriptor for the UI commands proxy. */ 29777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinetypedef struct UICmdProxy { 30777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine /* I/O associated with this descriptor. */ 31777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine LoopIo io; 32777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 33777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine /* Looper associated with this descriptor. */ 34777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine Looper* looper; 35777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 36777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine /* Writer to send UI commands. */ 37777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine SyncSocket* sync_writer; 38777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 39777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine /* Socket descriptor for this service. */ 40777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine int sock; 41777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine} UICmdProxy; 42777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 43777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* One and only one UICmdProxy instance. */ 44777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinestatic UICmdProxy _uiCmdProxy; 45777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 46777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* Implemented in android/console.c */ 47777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkineextern void destroy_uicmd_client(void); 48777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 49777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* Calculates timeout for transferring the given number of bytes via socket. 50777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * Return: 51777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * Number of milliseconds during which the entire number of bytes is expected 52777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * to be transferred via socket. 53777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine */ 54777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinestatic int 55777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine_uiCmdProxy_get_timeout(size_t data_size) 56777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine{ 57777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // Min 2 seconds + 10 millisec for each transferring byte. 58777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // TODO: Come up with a better arithmetics here. 59777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine return 2000 + data_size * 10; 60777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine} 61777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 62777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* Sends request to the UI client of this service. 63777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * Param: 64777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * cmd_type, cmd_param, cmd_param_size - Define the command to send. 65777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * Return: 66777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * 0 on success, or < 0 on failure. 67777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine */ 68777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinestatic int 69777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine_uiCmdProxy_send_command(uint8_t cmd_type, 70777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine void* cmd_param, 71777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine uint32_t cmd_param_size) 72777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine{ 73777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine UICmdHeader header; 74777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine int status = syncsocket_start_write(_uiCmdProxy.sync_writer); 75777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine if (!status) { 76777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // Initialize and send the header. 77777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine header.cmd_type = cmd_type; 78777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine header.cmd_param_size = cmd_param_size; 79777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine status = syncsocket_write(_uiCmdProxy.sync_writer, &header, sizeof(header), 80777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine _uiCmdProxy_get_timeout(sizeof(header))); 81777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // If there are command parameters, send them too. 82777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine if (status > 0 && cmd_param != NULL && cmd_param_size > 0) { 83777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine status = syncsocket_write(_uiCmdProxy.sync_writer, cmd_param, 84777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine cmd_param_size, 85777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine _uiCmdProxy_get_timeout(cmd_param_size)); 86777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine } 87777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine status = syncsocket_result(status); 88777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine syncsocket_stop_write(_uiCmdProxy.sync_writer); 89777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine } 90777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine if (status < 0) { 91777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine derror("Send UI command %d (%u bytes) has failed: %s\n", 92777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine cmd_type, cmd_param_size, errno_str); 93777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine } 94777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine return status; 95777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine} 96777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 97777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* Asynchronous I/O callback for UICmdProxy instance. 98777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * We expect this callback to be called only on UI detachment condition. In this 99777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * case the event should be LOOP_IO_READ, and read should fail with errno set 100777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * to ECONNRESET. 101777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * Param: 102777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * opaque - UICmdProxy instance. 103777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine */ 104777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinestatic void 105777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine_uiCmdProxy_io_func(void* opaque, int fd, unsigned events) 106777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine{ 107777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine UICmdProxy* uicmd = (UICmdProxy*)opaque; 108777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine AsyncReader reader; 109777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine AsyncStatus status; 110777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine uint8_t read_buf[1]; 111777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 112777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine if (events & LOOP_IO_WRITE) { 113777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine derror("Unexpected LOOP_IO_WRITE in _uiCmdProxy_io_func.\n"); 114777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine return; 115777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine } 116777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 117777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // Try to read 118777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine asyncReader_init(&reader, read_buf, sizeof(read_buf), &uicmd->io); 119f9e333ade2529f257ced6bcff8e5824cb07eacf9David 'Digit' Turner status = asyncReader_read(&reader); 120777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // We expect only error status here. 121777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine if (status != ASYNC_ERROR) { 122777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine derror("Unexpected read status %d in _uiCmdProxy_io_func\n", status); 123777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine return; 124777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine } 125777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // We expect only socket disconnection error here. 126777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine if (errno != ECONNRESET) { 127777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine derror("Unexpected read error %d (%s) in _uiCmdProxy_io_func.\n", 128777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine errno, errno_str); 129777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine return; 130777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine } 131777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 132777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // Client got disconnectted. 133777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine destroy_uicmd_client(); 134777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine} 135777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine/* a callback function called when the system wants to change the brightness 136777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * of a given light. 'light' is a string which can be one of: 137777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * 'lcd_backlight', 'button_backlight' or 'Keyboard_backlight' 138777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * 139777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * brightness is an integer (acceptable range are 0..255), however the 140777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * default is around 105, and we probably don't want to dim the emulator's 141777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine * output at that level. 142777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine */ 143777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinestatic void 144777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine_uiCmdProxy_brightness_change_callback(void* opaque, 145777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine const char* light, 146777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine int brightness) 147777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine{ 148777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // Calculate size of the command parameters. 149777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine const size_t cmd_size = sizeof(UICmdChangeDispBrightness) + strlen(light) + 1; 150777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // Allocate and initialize parameters. 151777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine UICmdChangeDispBrightness* cmd = 152777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine (UICmdChangeDispBrightness*)qemu_malloc(cmd_size); 153777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine cmd->brightness = brightness; 154777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine strcpy(cmd->light, light); 155777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // Send the command. 156777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine _uiCmdProxy_send_command(AUICMD_CHANGE_DISP_BRIGHTNESS, cmd, cmd_size); 157777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine qemu_free(cmd); 158777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine} 159777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 160777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkineint 161777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir ChtchetkineuiCmdProxy_create(int fd) 162777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine{ 163777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // Initialize the only UICmdProxy instance. 164777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine _uiCmdProxy.sock = fd; 165777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine _uiCmdProxy.looper = looper_newCore(); 166777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine loopIo_init(&_uiCmdProxy.io, _uiCmdProxy.looper, _uiCmdProxy.sock, 167777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine _uiCmdProxy_io_func, &_uiCmdProxy); 168777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine loopIo_wantRead(&_uiCmdProxy.io); 169777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine _uiCmdProxy.sync_writer = syncsocket_init(fd); 170777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine if (_uiCmdProxy.sync_writer == NULL) { 171777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine derror("Unable to initialize UICmdProxy writer: %s\n", errno_str); 172777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine uiCmdProxy_destroy(); 173777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine return -1; 174777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine } 175777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine { 176777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // Set brighness change callback, so we can notify 177777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // the UI about the event. 178777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine AndroidHwControlFuncs funcs; 179777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine funcs.light_brightness = _uiCmdProxy_brightness_change_callback; 180ca9505992288636908169d0389087b3ca5277d07David 'Digit' Turner android_hw_control_set(&_uiCmdProxy, &funcs); 181777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine } 182777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine return 0; 183777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine} 184777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 185777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinevoid 186777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir ChtchetkineuiCmdProxy_destroy() 187777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine{ 188777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // Destroy the sync writer. 189777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine if (_uiCmdProxy.sync_writer != NULL) { 190777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine syncsocket_close(_uiCmdProxy.sync_writer); 191777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine syncsocket_free(_uiCmdProxy.sync_writer); 192777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine } 193777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine if (_uiCmdProxy.looper != NULL) { 194777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine // Stop all I/O that may still be going on. 195777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine loopIo_done(&_uiCmdProxy.io); 196777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine looper_free(_uiCmdProxy.looper); 197777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine _uiCmdProxy.looper = NULL; 198777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine } 199777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine _uiCmdProxy.sock = -1; 200777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine} 201777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine 202777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkineint 203777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkineuicmd_set_window_scale(double scale, int is_dpi) 204777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine{ 205777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine UICmdSetWindowsScale cmd; 206777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine cmd.scale = scale; 207777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine cmd.is_dpi = is_dpi; 208777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine return _uiCmdProxy_send_command(AUICMD_SET_WINDOWS_SCALE, &cmd, sizeof(cmd)); 209777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine} 210