* Copyright 2001-2015, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* Caz <turok2@currantbun.com>
* Axel Dörfler, axeld@pinc-software.de
* Michael Lotz <mmlr@mlotz.ch>
* Wim van der Meer <WPJvanderMeer@gmail.com>
* Joseph Groover <looncraz@looncraz.net>
*/
#include <InterfaceDefs.h>
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Bitmap.h>
#include <Clipboard.h>
#include <ControlLook.h>
#include <Font.h>
#include <Menu.h>
#include <Point.h>
#include <Roster.h>
#include <Screen.h>
#include <ScrollBar.h>
#include <String.h>
#include <TextView.h>
#include <Window.h>
#include <ApplicationPrivate.h>
#include <AppServerLink.h>
#include <ColorConversion.h>
#include <DecorInfo.h>
#include <DefaultColors.h>
#include <DesktopLink.h>
#include <HaikuControlLook.h>
#include <InputServerTypes.h>
#include <input_globals.h>
#include <InterfacePrivate.h>
#include <MenuPrivate.h>
#include <pr_server.h>
#include <ServerProtocol.h>
#include <ServerReadOnlyMemory.h>
#include <truncate_string.h>
#include <utf8_functions.h>
#include <WidthBuffer.h>
#include <WindowInfo.h>
using namespace BPrivate;
struct general_ui_info {
rgb_color background_color;
rgb_color mark_color;
rgb_color highlight_color;
bool color_frame;
rgb_color window_frame_color;
};
struct general_ui_info general_info;
menu_info *_menu_info_ptr_;
extern "C" const char B_NOTIFICATION_SENDER[] = "be:sender";
static const rgb_color _kDefaultColors[kColorWhichCount] = {
{216, 216, 216, 255},
{216, 216, 216, 255},
{255, 203, 0, 255},
{0, 0, 229, 255},
{51, 102, 152, 255},
{153, 153, 153, 255},
{0, 0, 0, 255},
{0, 0, 0, 255},
{0, 0, 0, 255},
{0, 0, 0, 255},
{255, 255, 255, 255},
{0, 0, 0, 255},
{222, 222, 222, 255},
{0, 0, 0, 255},
{172, 172, 172, 255},
{102, 152, 203, 255},
{0, 0, 0, 255},
{255, 255, 255, 255},
{0, 0, 0, 255},
{255, 255, 216, 255},
{0, 0, 0, 255},
{0, 0, 0, 255},
{232, 232, 232, 255},
{80, 80, 80, 255},
{224, 224, 224, 255},
{232, 232, 232, 255},
{27, 82, 140, 255},
{255, 255, 255, 255},
{190, 190, 190, 255},
{0, 0, 0, 255},
{0, 0, 0, 255},
{216, 216, 216, 255},
{51, 102, 187, 255},
{102, 152, 203, 255},
{145, 112, 155, 255},
{121, 142, 203, 255},
{50, 150, 255, 255},
{46, 204, 64, 255},
{255, 65, 54, 255},
{}
};
const rgb_color* BPrivate::kDefaultColors = &_kDefaultColors[0];
static const rgb_color _kDefaultColorsDark[kColorWhichCount] = {
{43, 43, 43, 255},
{28, 28, 28, 255},
{227, 73, 17, 255},
{0, 0, 229, 255},
{51, 102, 152, 255},
{90, 90, 90, 255},
{255, 255, 255, 255},
{255, 255, 255, 255},
{0, 0, 0, 255},
{253, 253, 253, 255},
{0, 0, 0, 255},
{234, 234, 234, 255},
{29, 29, 29, 255},
{230, 230, 230, 255},
{195, 195, 195, 255},
{75, 124, 168, 255},
{0, 0, 0, 255},
{255, 255, 255, 255},
{0, 0, 0, 255},
{76, 68, 79, 255},
{255, 255, 255, 255},
{255, 255, 255, 255},
{203, 32, 9, 255},
{255, 255, 255, 255},
{227, 73, 17, 255},
{203, 32, 9, 255},
{27, 82, 140, 255},
{0, 0, 0, 255},
{90, 90, 90, 255},
{255, 255, 255, 255},
{255, 255, 255, 255},
{39, 39, 39, 255},
{106, 112, 212, 255},
{102, 152, 203, 255},
{145, 112, 155, 255},
{121, 142, 203, 255},
{50, 150, 255, 255},
{46, 204, 64, 255},
{255, 40, 54, 255},
{}
};
static const char* kColorNames[kColorWhichCount] = {
"B_PANEL_BACKGROUND_COLOR",
"B_MENU_BACKGROUND_COLOR",
"B_WINDOW_TAB_COLOR",
"B_KEYBOARD_NAVIGATION_COLOR",
"B_DESKTOP_COLOR",
"B_MENU_SELECTED_BACKGROUND_COLOR",
"B_MENU_ITEM_TEXT_COLOR",
"B_MENU_SELECTED_ITEM_TEXT_COLOR",
"B_MENU_SELECTED_BORDER_COLOR",
"B_PANEL_TEXT_COLOR",
"B_DOCUMENT_BACKGROUND_COLOR",
"B_DOCUMENT_TEXT_COLOR",
"B_CONTROL_BACKGROUND_COLOR",
"B_CONTROL_TEXT_COLOR",
"B_CONTROL_BORDER_COLOR",
"B_CONTROL_HIGHLIGHT_COLOR",
"B_NAVIGATION_PULSE_COLOR",
"B_SHINE_COLOR",
"B_SHADOW_COLOR",
"B_TOOLTIP_BACKGROUND_COLOR",
"B_TOOLTIP_TEXT_COLOR",
"B_WINDOW_TEXT_COLOR",
"B_WINDOW_INACTIVE_TAB_COLOR",
"B_WINDOW_INACTIVE_TEXT_COLOR",
"B_WINDOW_BORDER_COLOR",
"B_WINDOW_INACTIVE_BORDER_COLOR",
"B_CONTROL_MARK_COLOR",
"B_LIST_BACKGROUND_COLOR",
"B_LIST_SELECTED_BACKGROUND_COLOR",
"B_LIST_ITEM_TEXT_COLOR",
"B_LIST_SELECTED_ITEM_TEXT_COLOR",
"B_SCROLL_BAR_THUMB_COLOR",
"B_LINK_TEXT_COLOR",
"B_LINK_HOVER_COLOR",
"B_LINK_VISITED_COLOR",
"B_LINK_ACTIVE_COLOR",
"B_STATUS_BAR_COLOR",
"B_SUCCESS_COLOR",
"B_FAILURE_COLOR",
NULL
};
static image_id sControlLookAddon = -1;
namespace BPrivate {
to the window screen's mode.
Returns \c true if the mode is known.
*/
bool
get_mode_parameter(uint32 mode, int32& width, int32& height,
uint32& colorSpace)
{
switch (mode) {
case B_8_BIT_640x480:
case B_8_BIT_800x600:
case B_8_BIT_1024x768:
case B_8_BIT_1152x900:
case B_8_BIT_1280x1024:
case B_8_BIT_1600x1200:
colorSpace = B_CMAP8;
break;
case B_15_BIT_640x480:
case B_15_BIT_800x600:
case B_15_BIT_1024x768:
case B_15_BIT_1152x900:
case B_15_BIT_1280x1024:
case B_15_BIT_1600x1200:
colorSpace = B_RGB15;
break;
case B_16_BIT_640x480:
case B_16_BIT_800x600:
case B_16_BIT_1024x768:
case B_16_BIT_1152x900:
case B_16_BIT_1280x1024:
case B_16_BIT_1600x1200:
colorSpace = B_RGB16;
break;
case B_32_BIT_640x480:
case B_32_BIT_800x600:
case B_32_BIT_1024x768:
case B_32_BIT_1152x900:
case B_32_BIT_1280x1024:
case B_32_BIT_1600x1200:
colorSpace = B_RGB32;
break;
default:
return false;
}
switch (mode) {
case B_8_BIT_640x480:
case B_15_BIT_640x480:
case B_16_BIT_640x480:
case B_32_BIT_640x480:
width = 640; height = 480;
break;
case B_8_BIT_800x600:
case B_15_BIT_800x600:
case B_16_BIT_800x600:
case B_32_BIT_800x600:
width = 800; height = 600;
break;
case B_8_BIT_1024x768:
case B_15_BIT_1024x768:
case B_16_BIT_1024x768:
case B_32_BIT_1024x768:
width = 1024; height = 768;
break;
case B_8_BIT_1152x900:
case B_15_BIT_1152x900:
case B_16_BIT_1152x900:
case B_32_BIT_1152x900:
width = 1152; height = 900;
break;
case B_8_BIT_1280x1024:
case B_15_BIT_1280x1024:
case B_16_BIT_1280x1024:
case B_32_BIT_1280x1024:
width = 1280; height = 1024;
break;
case B_8_BIT_1600x1200:
case B_15_BIT_1600x1200:
case B_16_BIT_1600x1200:
case B_32_BIT_1600x1200:
width = 1600; height = 1200;
break;
}
return true;
}
void
get_workspaces_layout(uint32* _columns, uint32* _rows)
{
int32 columns = 1;
int32 rows = 1;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_WORKSPACE_LAYOUT);
status_t status;
if (link.FlushWithReply(status) == B_OK && status == B_OK) {
link.Read<int32>(&columns);
link.Read<int32>(&rows);
}
if (_columns != NULL)
*_columns = columns;
if (_rows != NULL)
*_rows = rows;
}
void
set_workspaces_layout(uint32 columns, uint32 rows)
{
if (columns < 1 || rows < 1)
return;
BPrivate::AppServerLink link;
link.StartMessage(AS_SET_WORKSPACE_LAYOUT);
link.Attach<int32>(columns);
link.Attach<int32>(rows);
link.Flush();
}
}
void
set_subpixel_antialiasing(bool subpix)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_SET_SUBPIXEL_ANTIALIASING);
link.Attach<bool>(subpix);
link.Flush();
}
status_t
get_subpixel_antialiasing(bool* subpix)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_SUBPIXEL_ANTIALIASING);
int32 status = B_ERROR;
if (link.FlushWithReply(status) != B_OK || status < B_OK)
return status;
link.Read<bool>(subpix);
return B_OK;
}
void
set_hinting_mode(uint8 hinting)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_SET_HINTING);
link.Attach<uint8>(hinting);
link.Flush();
}
status_t
get_hinting_mode(uint8* hinting)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_HINTING);
int32 status = B_ERROR;
if (link.FlushWithReply(status) != B_OK || status < B_OK)
return status;
link.Read<uint8>(hinting);
return B_OK;
}
void
set_average_weight(uint8 averageWeight)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_SET_SUBPIXEL_AVERAGE_WEIGHT);
link.Attach<uint8>(averageWeight);
link.Flush();
}
status_t
get_average_weight(uint8* averageWeight)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_SUBPIXEL_AVERAGE_WEIGHT);
int32 status = B_ERROR;
if (link.FlushWithReply(status) != B_OK || status < B_OK)
return status;
link.Read<uint8>(averageWeight);
return B_OK;
}
void
set_is_subpixel_ordering_regular(bool subpixelOrdering)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_SET_SUBPIXEL_ORDERING);
link.Attach<bool>(subpixelOrdering);
link.Flush();
}
status_t
get_is_subpixel_ordering_regular(bool* subpixelOrdering)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_SUBPIXEL_ORDERING);
int32 status = B_ERROR;
if (link.FlushWithReply(status) != B_OK || status < B_OK)
return status;
link.Read<bool>(subpixelOrdering);
return B_OK;
}
const color_map *
system_colors()
{
return BScreen(B_MAIN_SCREEN_ID).ColorMap();
}
status_t
set_screen_space(int32 index, uint32 space, bool stick)
{
int32 width;
int32 height;
uint32 depth;
if (!BPrivate::get_mode_parameter(space, width, height, depth))
return B_BAD_VALUE;
BScreen screen(B_MAIN_SCREEN_ID);
display_mode mode;
status_t status = screen.GetMode(index, &mode);
if (status < B_OK)
return status;
mode.virtual_width = width;
mode.virtual_height = height;
mode.space = depth;
return screen.SetMode(index, &mode, stick);
}
status_t
get_scroll_bar_info(scroll_bar_info *info)
{
if (info == NULL)
return B_BAD_VALUE;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_SCROLLBAR_INFO);
int32 code;
if (link.FlushWithReply(code) == B_OK
&& code == B_OK) {
link.Read<scroll_bar_info>(info);
return B_OK;
}
return B_ERROR;
}
status_t
set_scroll_bar_info(scroll_bar_info *info)
{
if (info == NULL)
return B_BAD_VALUE;
BPrivate::AppServerLink link;
int32 code;
link.StartMessage(AS_SET_SCROLLBAR_INFO);
link.Attach<scroll_bar_info>(*info);
if (link.FlushWithReply(code) == B_OK
&& code == B_OK)
return B_OK;
return B_ERROR;
}
status_t
get_mouse_type(int32 *type)
{
BMessage command(IS_GET_MOUSE_TYPE);
BMessage reply;
status_t err = _control_input_server_(&command, &reply);
if (err != B_OK)
return err;
return reply.FindInt32("mouse_type", type);
}
status_t
set_mouse_type(int32 type)
{
BMessage command(IS_SET_MOUSE_TYPE);
BMessage reply;
status_t err = command.AddInt32("mouse_type", type);
if (err != B_OK)
return err;
return _control_input_server_(&command, &reply);
}
status_t
get_mouse_type(const char* mouse_name, int32 *type)
{
BMessage command(IS_GET_MOUSE_TYPE);
BMessage reply;
command.AddString("mouse_name", mouse_name);
status_t err = _control_input_server_(&command, &reply);
if (err != B_OK)
return err;
return reply.FindInt32("mouse_type", type);
}
status_t
set_mouse_type(const char* mouse_name, int32 type)
{
BMessage command(IS_SET_MOUSE_TYPE);
BMessage reply;
status_t err_mouse_name = command.AddString("mouse_name", mouse_name);
if (err_mouse_name != B_OK)
return err_mouse_name;
status_t err = command.AddInt32("mouse_type", type);
if (err != B_OK)
return err;
return _control_input_server_(&command, &reply);
}
status_t
get_mouse_map(mouse_map* map)
{
return get_mouse_map("", map);
}
status_t
set_mouse_map(mouse_map* map)
{
return set_mouse_map("", map);
}
status_t
get_mouse_map(const char* mouse_name, mouse_map* map)
{
BMessage command(IS_GET_MOUSE_MAP);
BMessage reply;
const void *data = 0;
ssize_t count;
status_t err = command.AddString("mouse_name", mouse_name);
if (err == B_OK)
err = _control_input_server_(&command, &reply);
if (err == B_OK)
err = reply.FindData("mousemap", B_RAW_TYPE, &data, &count);
if (err == B_OK)
memcpy(map, data, count);
return err;
}
status_t
set_mouse_map(const char* mouse_name, mouse_map* map)
{
BMessage command(IS_SET_MOUSE_MAP);
BMessage reply;
status_t err = command.AddString("mouse_name", mouse_name);
if (err == B_OK)
err = command.AddData("mousemap", B_RAW_TYPE, map, sizeof(mouse_map));
if (err != B_OK)
return err;
return _control_input_server_(&command, &reply);
}
status_t
get_click_speed(bigtime_t* speed)
{
return get_click_speed("", speed);
}
status_t
set_click_speed(bigtime_t speed)
{
return set_click_speed("", speed);
}
status_t
get_click_speed(const char* mouse_name, bigtime_t* speed)
{
BMessage command(IS_GET_CLICK_SPEED);
BMessage reply;
status_t err = command.AddString("mouse_name", mouse_name);
if (err == B_OK)
err = _control_input_server_(&command, &reply);
if (err != B_OK)
return err;
if (reply.FindInt64("speed", speed) != B_OK)
*speed = 500000;
return B_OK;
}
status_t
set_click_speed(const char* mouse_name, bigtime_t speed)
{
BMessage command(IS_SET_CLICK_SPEED);
BMessage reply;
status_t err = command.AddString("mouse_name", mouse_name);
if (err == B_OK)
err = command.AddInt64("speed", speed);
if (err != B_OK)
return err;
return _control_input_server_(&command, &reply);
}
status_t
get_mouse_speed(int32 *speed)
{
BMessage command(IS_GET_MOUSE_SPEED);
BMessage reply;
status_t err = _control_input_server_(&command, &reply);
if (err != B_OK)
return err;
if (reply.FindInt32("speed", speed) != B_OK)
*speed = 65536;
return B_OK;
}
status_t
set_mouse_speed(int32 speed)
{
BMessage command(IS_SET_MOUSE_SPEED);
BMessage reply;
command.AddInt32("speed", speed);
return _control_input_server_(&command, &reply);
}
status_t
get_mouse_speed(const char* mouse_name, int32 *speed)
{
BMessage command(IS_GET_MOUSE_SPEED);
BMessage reply;
command.AddString("mouse_name", mouse_name);
status_t err = _control_input_server_(&command, &reply);
if (err != B_OK)
return err;
err = reply.FindInt32("speed", speed);
if (err != B_OK)
return err;
return B_OK;
}
status_t
set_mouse_speed(const char* mouse_name, int32 speed)
{
BMessage command(IS_SET_MOUSE_SPEED);
BMessage reply;
command.AddString("mouse_name", mouse_name);
command.AddInt32("speed", speed);
return _control_input_server_(&command, &reply);
}
status_t
get_mouse_acceleration(int32 *speed)
{
BMessage command(IS_GET_MOUSE_ACCELERATION);
BMessage reply;
_control_input_server_(&command, &reply);
if (reply.FindInt32("speed", speed) != B_OK)
*speed = 65536;
return B_OK;
}
status_t
set_mouse_acceleration(int32 speed)
{
BMessage command(IS_SET_MOUSE_ACCELERATION);
BMessage reply;
command.AddInt32("speed", speed);
return _control_input_server_(&command, &reply);
}
status_t
get_mouse_acceleration(const char* mouse_name, int32 *speed)
{
BMessage command(IS_GET_MOUSE_ACCELERATION);
BMessage reply;
command.AddString("mouse_name", mouse_name);
_control_input_server_(&command, &reply);
if (reply.FindInt32("speed", speed) != B_OK)
*speed = 65536;
return B_OK;
}
status_t
set_mouse_acceleration(const char* mouse_name, int32 speed)
{
BMessage command(IS_SET_MOUSE_ACCELERATION);
BMessage reply;
command.AddString("mouse_name", mouse_name);
command.AddInt32("speed", speed);
return _control_input_server_(&command, &reply);
}
status_t
get_key_repeat_rate(int32 *rate)
{
BMessage command(IS_GET_KEY_REPEAT_RATE);
BMessage reply;
status_t err = _control_input_server_(&command, &reply);
if (err == B_OK)
err = reply.FindInt32("rate", rate);
if (err != B_OK) {
*rate = 250000;
return err;
}
return B_OK;
}
status_t
set_key_repeat_rate(int32 rate)
{
BMessage command(IS_SET_KEY_REPEAT_RATE);
BMessage reply;
command.AddInt32("rate", rate);
return _control_input_server_(&command, &reply);
}
status_t
get_key_repeat_delay(bigtime_t *delay)
{
BMessage command(IS_GET_KEY_REPEAT_DELAY);
BMessage reply;
status_t err = _control_input_server_(&command, &reply);
if (err == B_OK)
err = reply.FindInt64("delay", delay);
if (err != B_OK) {
*delay = 200;
return err;
}
return B_OK;
}
status_t
set_key_repeat_delay(bigtime_t delay)
{
BMessage command(IS_SET_KEY_REPEAT_DELAY);
BMessage reply;
command.AddInt64("delay", delay);
return _control_input_server_(&command, &reply);
}
uint32
modifiers()
{
BMessage command(IS_GET_MODIFIERS);
BMessage reply;
int32 err, modifier;
_control_input_server_(&command, &reply);
if (reply.FindInt32("status", &err) != B_OK)
return 0;
if (reply.FindInt32("modifiers", &modifier) != B_OK)
return 0;
return modifier;
}
status_t
get_key_info(key_info *info)
{
BMessage command(IS_GET_KEY_INFO);
BMessage reply;
const void *data = 0;
int32 err;
ssize_t count;
_control_input_server_(&command, &reply);
if (reply.FindInt32("status", &err) != B_OK)
return B_ERROR;
if (reply.FindData("key_info", B_ANY_TYPE, &data, &count) != B_OK)
return B_ERROR;
memcpy(info, data, count);
return B_OK;
}
void
get_key_map(key_map **map, char **key_buffer)
{
_get_key_map(map, key_buffer, NULL);
}
void
_get_key_map(key_map **map, char **key_buffer, ssize_t *key_buffer_size)
{
BMessage command(IS_GET_KEY_MAP);
BMessage reply;
ssize_t map_count, key_count;
const void *map_array = 0, *key_array = 0;
if (key_buffer_size == NULL)
key_buffer_size = &key_count;
_control_input_server_(&command, &reply);
if (reply.FindData("keymap", B_ANY_TYPE, &map_array, &map_count) != B_OK) {
*map = 0; *key_buffer = 0;
return;
}
if (reply.FindData("key_buffer", B_ANY_TYPE, &key_array, key_buffer_size)
!= B_OK) {
*map = 0; *key_buffer = 0;
return;
}
*map = (key_map *)malloc(map_count);
memcpy(*map, map_array, map_count);
*key_buffer = (char *)malloc(*key_buffer_size);
memcpy(*key_buffer, key_array, *key_buffer_size);
}
status_t
get_keyboard_id(uint16 *id)
{
BMessage command(IS_GET_KEYBOARD_ID);
BMessage reply;
uint16 kid;
_control_input_server_(&command, &reply);
status_t err = reply.FindInt16("id", (int16 *)&kid);
if (err != B_OK)
return err;
*id = kid;
return B_OK;
}
status_t
get_modifier_key(uint32 modifier, uint32 *key)
{
BMessage command(IS_GET_MODIFIER_KEY);
BMessage reply;
uint32 rkey;
command.AddInt32("modifier", modifier);
_control_input_server_(&command, &reply);
status_t err = reply.FindInt32("key", (int32 *) &rkey);
if (err != B_OK)
return err;
*key = rkey;
return B_OK;
}
void
set_modifier_key(uint32 modifier, uint32 key)
{
BMessage command(IS_SET_MODIFIER_KEY);
BMessage reply;
command.AddInt32("modifier", modifier);
command.AddInt32("key", key);
_control_input_server_(&command, &reply);
}
void
set_keyboard_locks(uint32 modifiers)
{
BMessage command(IS_SET_KEYBOARD_LOCKS);
BMessage reply;
command.AddInt32("locks", modifiers);
_control_input_server_(&command, &reply);
}
status_t
_restore_key_map_()
{
BMessage message(IS_RESTORE_KEY_MAP);
BMessage reply;
return _control_input_server_(&message, &reply);
}
rgb_color
keyboard_navigation_color()
{
return ui_color(B_KEYBOARD_NAVIGATION_COLOR);
}
int32
count_workspaces()
{
uint32 columns;
uint32 rows;
BPrivate::get_workspaces_layout(&columns, &rows);
return columns * rows;
}
void
set_workspace_count(int32 count)
{
int32 squareRoot = (int32)sqrt(count);
int32 rows = 1;
for (int32 i = 2; i <= squareRoot; i++) {
if (count % i == 0)
rows = i;
}
int32 columns = count / rows;
BPrivate::set_workspaces_layout(columns, rows);
}
int32
current_workspace()
{
int32 index = 0;
BPrivate::AppServerLink link;
link.StartMessage(AS_CURRENT_WORKSPACE);
int32 status;
if (link.FlushWithReply(status) == B_OK && status == B_OK)
link.Read<int32>(&index);
return index;
}
void
activate_workspace(int32 workspace)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_ACTIVATE_WORKSPACE);
link.Attach<int32>(workspace);
link.Attach<bool>(false);
link.Flush();
}
bigtime_t
idle_time()
{
bigtime_t idletime = 0;
BPrivate::AppServerLink link;
link.StartMessage(AS_IDLE_TIME);
int32 code;
if (link.FlushWithReply(code) == B_OK && code == B_OK)
link.Read<int64>(&idletime);
return idletime;
}
void
run_select_printer_panel()
{
if (be_roster == NULL)
return;
be_roster->Launch(PRNT_SIGNATURE_TYPE);
}
void
run_add_printer_panel()
{
run_select_printer_panel();
BMessenger printerPanelMessenger(PRNT_SIGNATURE_TYPE);
printerPanelMessenger.SendMessage(PRINTERS_ADD_PRINTER);
}
void
run_be_about()
{
if (be_roster != NULL)
be_roster->Launch("application/x-vnd.Haiku-About");
}
void
set_focus_follows_mouse(bool follow)
{
set_mouse_mode(follow ? B_FOCUS_FOLLOWS_MOUSE : B_NORMAL_MOUSE);
}
bool
focus_follows_mouse()
{
return mouse_mode() == B_FOCUS_FOLLOWS_MOUSE;
}
void
set_mouse_mode(mode_mouse mode)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_SET_MOUSE_MODE);
link.Attach<mode_mouse>(mode);
link.Flush();
}
mode_mouse
mouse_mode()
{
mode_mouse mode = B_NORMAL_MOUSE;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_MOUSE_MODE);
int32 code;
if (link.FlushWithReply(code) == B_OK && code == B_OK)
link.Read<mode_mouse>(&mode);
return mode;
}
void
set_focus_follows_mouse_mode(mode_focus_follows_mouse mode)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_SET_FOCUS_FOLLOWS_MOUSE_MODE);
link.Attach<mode_focus_follows_mouse>(mode);
link.Flush();
}
mode_focus_follows_mouse
focus_follows_mouse_mode()
{
mode_focus_follows_mouse mode = B_NORMAL_FOCUS_FOLLOWS_MOUSE;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_FOCUS_FOLLOWS_MOUSE_MODE);
int32 code;
if (link.FlushWithReply(code) == B_OK && code == B_OK)
link.Read<mode_focus_follows_mouse>(&mode);
return mode;
}
status_t
get_mouse(BPoint* screenWhere, uint32* buttons)
{
if (screenWhere == NULL && buttons == NULL)
return B_BAD_VALUE;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_CURSOR_POSITION);
int32 code;
status_t ret = link.FlushWithReply(code);
if (ret != B_OK)
return ret;
if (code != B_OK)
return code;
if (screenWhere != NULL)
ret = link.Read<BPoint>(screenWhere);
else {
BPoint dummy;
ret = link.Read<BPoint>(&dummy);
}
if (ret != B_OK)
return ret;
if (buttons != NULL)
ret = link.Read<uint32>(buttons);
else {
uint32 dummy;
ret = link.Read<uint32>(&dummy);
}
return ret;
}
status_t
get_mouse_bitmap(BBitmap** bitmap, BPoint* hotspot)
{
if (bitmap == NULL && hotspot == NULL)
return B_BAD_VALUE;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_CURSOR_BITMAP);
int32 code;
status_t status = link.FlushWithReply(code);
if (status != B_OK)
return status;
if (code != B_OK)
return code;
uint32 size = 0;
uint32 cursorWidth = 0;
uint32 cursorHeight = 0;
color_space colorspace = B_RGBA32;
link.Read<uint32>(&size);
link.Read<uint32>(&cursorWidth);
link.Read<uint32>(&cursorHeight);
link.Read<color_space>(&colorspace);
if (hotspot == NULL) {
BPoint dummy;
link.Read<BPoint>(&dummy);
} else
link.Read<BPoint>(hotspot);
void* data = NULL;
if (size > 0)
data = malloc(size);
if (data == NULL)
return B_NO_MEMORY;
status = link.Read(data, size);
if (status != B_OK) {
free(data);
return status;
}
BBitmap* cursorBitmap = new (std::nothrow) BBitmap(BRect(0, 0,
cursorWidth - 1, cursorHeight - 1), colorspace);
if (cursorBitmap == NULL) {
free(data);
return B_NO_MEMORY;
}
status = cursorBitmap->InitCheck();
if (status == B_OK)
cursorBitmap->SetBits(data, size, 0, colorspace);
free(data);
if (status == B_OK && bitmap != NULL)
*bitmap = cursorBitmap;
else
delete cursorBitmap;
return status;
}
void
set_accept_first_click(bool acceptFirstClick)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_SET_ACCEPT_FIRST_CLICK);
link.Attach<bool>(acceptFirstClick);
link.Flush();
}
bool
accept_first_click()
{
bool acceptFirstClick = true;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_ACCEPT_FIRST_CLICK);
int32 code;
if (link.FlushWithReply(code) == B_OK && code == B_OK)
link.Read<bool>(&acceptFirstClick);
return acceptFirstClick;
}
rgb_color
ui_color(color_which which)
{
int32 index = color_which_to_index(which);
if (index < 0 || index >= kColorWhichCount) {
fprintf(stderr, "ui_color(): unknown color_which %d\n", which);
return make_color(0, 0, 0);
}
if (be_app != NULL) {
server_read_only_memory* shared
= BApplication::Private::ServerReadOnlyMemory();
if (shared != NULL) {
if (shared->colors[index] == B_TRANSPARENT_COLOR)
shared->colors[index] = _kDefaultColors[index];
return shared->colors[index];
}
}
return _kDefaultColors[index];
}
rgb_color
BPrivate::GetSystemColor(color_which colorConstant, bool darkVariant) {
if (darkVariant) {
return _kDefaultColorsDark[color_which_to_index(colorConstant)];
} else {
return _kDefaultColors[color_which_to_index(colorConstant)];
}
}
const char*
ui_color_name(color_which which)
{
if (which == B_NO_COLOR)
return NULL;
int32 index = color_which_to_index(which);
if (index < 0 || index >= kColorWhichCount) {
fprintf(stderr, "ui_color_name(): unknown color_which %d\n", which);
return NULL;
}
return kColorNames[index];
}
color_which
which_ui_color(const char* name)
{
if (name == NULL)
return B_NO_COLOR;
for (int32 index = 0; index < kColorWhichCount; ++index) {
if (!strcmp(kColorNames[index], name))
return index_to_color_which(index);
}
return B_NO_COLOR;
}
void
set_ui_color(const color_which &which, const rgb_color &color)
{
int32 index = color_which_to_index(which);
if (index < 0 || index >= kColorWhichCount) {
fprintf(stderr, "set_ui_color(): unknown color_which %d\n", which);
return;
}
if (ui_color(which) == color)
return;
BPrivate::DesktopLink link;
link.StartMessage(AS_SET_UI_COLOR);
link.Attach<color_which>(which);
link.Attach<rgb_color>(color);
link.Flush();
}
void
set_ui_colors(const BMessage* colors)
{
if (colors == NULL)
return;
int32 count = 0;
int32 index = 0;
char* name = NULL;
type_code type;
rgb_color color;
color_which which = B_NO_COLOR;
BPrivate::DesktopLink desktop;
if (desktop.InitCheck() != B_OK)
return;
desktop.StartMessage(AS_SET_UI_COLORS);
desktop.Attach<bool>(false);
while (colors->GetInfo(B_RGB_32_BIT_TYPE, index, &name, &type) == B_OK) {
which = which_ui_color(name);
++index;
if (which == B_NO_COLOR || colors->FindColor(name, &color) != B_OK)
continue;
desktop.Attach<color_which>(which);
desktop.Attach<rgb_color>(color);
++count;
}
if (count == 0)
return;
desktop.Attach<color_which>(B_NO_COLOR);
desktop.Flush();
}
rgb_color
tint_color(rgb_color color, float tint)
{
rgb_color result;
#define LIGHTEN(x) ((uint8)(255.0f - (255.0f - x) * tint))
#define DARKEN(x) ((uint8)(x * (2 - tint)))
if (tint < 1.0f) {
result.red = LIGHTEN(color.red);
result.green = LIGHTEN(color.green);
result.blue = LIGHTEN(color.blue);
result.alpha = color.alpha;
} else {
result.red = DARKEN(color.red);
result.green = DARKEN(color.green);
result.blue = DARKEN(color.blue);
result.alpha = color.alpha;
}
#undef LIGHTEN
#undef DARKEN
return result;
}
rgb_color shift_color(rgb_color color, float shift);
rgb_color
shift_color(rgb_color color, float shift)
{
return tint_color(color, shift);
}
extern "C" status_t
_init_interface_kit_()
{
status_t status = BPrivate::PaletteConverter::InitializeDefault(true);
if (status < B_OK)
return status;
if (be_clipboard == NULL)
be_clipboard = new BClipboard(NULL);
BString path;
if (get_control_look(path) && path.Length() > 0) {
BControlLook* (*instantiate)(image_id);
sControlLookAddon = load_add_on(path.String());
if (sControlLookAddon >= 0
&& get_image_symbol(sControlLookAddon,
"instantiate_control_look",
B_SYMBOL_TYPE_TEXT, (void **)&instantiate) == B_OK) {
be_control_look = instantiate(sControlLookAddon);
if (be_control_look == NULL) {
unload_add_on(sControlLookAddon);
sControlLookAddon = -1;
}
}
}
if (be_control_look == NULL)
be_control_look = new HaikuControlLook();
_init_global_fonts_();
BPrivate::gWidthBuffer = new BPrivate::WidthBuffer;
status = BPrivate::MenuPrivate::CreateBitmaps();
if (status != B_OK)
return status;
_menu_info_ptr_ = &BMenu::sMenuInfo;
status = get_menu_info(&BMenu::sMenuInfo);
if (status != B_OK)
return status;
general_info.background_color = ui_color(B_PANEL_BACKGROUND_COLOR);
general_info.mark_color = ui_color(B_CONTROL_MARK_COLOR);
general_info.highlight_color = ui_color(B_CONTROL_HIGHLIGHT_COLOR);
general_info.window_frame_color = ui_color(B_WINDOW_TAB_COLOR);
general_info.color_frame = true;
return status;
}
extern "C" status_t
_fini_interface_kit_()
{
BPrivate::MenuPrivate::DeleteBitmaps();
delete BPrivate::gWidthBuffer;
BPrivate::gWidthBuffer = NULL;
delete be_control_look;
be_control_look = NULL;
if (sControlLookAddon >= 0)
unload_add_on(sControlLookAddon);
sControlLookAddon = -1;
return B_OK;
}
namespace BPrivate {
\param path BString into which to store current decorator's location
\return boolean true/false
*/
bool
get_decorator(BString& path)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_DECORATOR);
int32 code;
if (link.FlushWithReply(code) != B_OK || code != B_OK)
return false;
return link.ReadString(path) == B_OK;
}
\param path BString with the path to the decorator to set
Will return detailed error status via status_t
*/
status_t
set_decorator(const BString& path)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_SET_DECORATOR);
link.AttachString(path.String());
status_t error = B_OK;
if (link.FlushWithReply(error) != B_OK)
return B_ERROR;
return error;
}
\param path path to any given decorator add-on
\param window pointer to BWindow which will show decorator
Piggy-backs on BWindow::SetDecoratorSettings(...)
*/
status_t
preview_decorator(const BString& path, BWindow* window)
{
if (window == NULL)
return B_ERROR;
BMessage msg('prVu');
msg.AddString("preview", path.String());
return window->SetDecoratorSettings(msg);
}
\param path BString into which to store current ControlLook's add-on path
\return boolean true/false
*/
bool
get_control_look(BString& path)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_CONTROL_LOOK);
int32 code;
if (link.FlushWithReply(code) != B_OK || code != B_OK)
return false;
return link.ReadString(path) == B_OK;
}
\param BString with the ControlLook add-on path to set
Will return detailed error status via status_t
*/
status_t
set_control_look(const BString& path)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_SET_CONTROL_LOOK);
link.AttachString(path.String());
status_t error = B_OK;
if (link.FlushWithReply(error) != B_OK)
return B_ERROR;
return error;
}
status_t
get_application_order(int32 workspace, team_id** _applications,
int32* _count)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_APPLICATION_ORDER);
link.Attach<int32>(workspace);
int32 code;
status_t status = link.FlushWithReply(code);
if (status != B_OK)
return status;
if (code != B_OK)
return code;
int32 count;
link.Read<int32>(&count);
*_applications = (team_id*)malloc(count * sizeof(team_id));
if (*_applications == NULL)
return B_NO_MEMORY;
link.Read(*_applications, count * sizeof(team_id));
*_count = count;
return B_OK;
}
status_t
get_window_order(int32 workspace, int32** _tokens, int32* _count)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_WINDOW_ORDER);
link.Attach<int32>(workspace);
int32 code;
status_t status = link.FlushWithReply(code);
if (status != B_OK)
return status;
if (code != B_OK)
return code;
int32 count;
link.Read<int32>(&count);
*_tokens = (int32*)malloc(count * sizeof(int32));
if (*_tokens == NULL)
return B_NO_MEMORY;
link.Read(*_tokens, count * sizeof(int32));
*_count = count;
return B_OK;
}
}
void
do_window_action(int32 windowToken, int32 action, BRect zoomRect, bool zoom)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_WINDOW_ACTION);
link.Attach<int32>(windowToken);
link.Attach<int32>(action);
link.Flush();
}
client_window_info*
get_window_info(int32 serverToken)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_WINDOW_INFO);
link.Attach<int32>(serverToken);
int32 code;
if (link.FlushWithReply(code) != B_OK || code != B_OK)
return NULL;
int32 size;
link.Read<int32>(&size);
client_window_info* info = (client_window_info*)malloc(size);
if (info == NULL)
return NULL;
link.Read(info, size);
return info;
}
int32*
get_token_list(team_id team, int32* _count)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_WINDOW_LIST);
link.Attach<team_id>(team);
int32 code;
if (link.FlushWithReply(code) != B_OK || code != B_OK)
return NULL;
int32 count;
link.Read<int32>(&count);
int32* tokens = (int32*)malloc(count * sizeof(int32));
if (tokens == NULL)
return NULL;
link.Read(tokens, count * sizeof(int32));
*_count = count;
return tokens;
}
void
do_bring_to_front_team(BRect zoomRect, team_id team, bool zoom)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_BRING_TEAM_TO_FRONT);
link.Attach<team_id>(team);
link.Flush();
}
void
do_minimize_team(BRect zoomRect, team_id team, bool zoom)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_MINIMIZE_TEAM);
link.Attach<team_id>(team);
link.Flush();
}
void
truncate_string(BString& string, uint32 mode, float width,
const float* escapementArray, float fontSize, float ellipsisWidth,
int32 charCount)
{
width += 1.f / 128;
switch (mode) {
case B_TRUNCATE_BEGINNING:
{
float totalWidth = 0;
for (int32 i = charCount - 1; i >= 0; i--) {
float charWidth = escapementArray[i] * fontSize;
if (totalWidth + charWidth > width) {
while (totalWidth + ellipsisWidth > width) {
if (++i == charCount) {
string.Truncate(0);
return;
}
totalWidth -= escapementArray[i] * fontSize;
}
string.RemoveChars(0, i + 1);
string.PrependChars(B_UTF8_ELLIPSIS, 1);
return;
}
totalWidth += charWidth;
}
break;
}
case B_TRUNCATE_END:
{
float totalWidth = 0;
for (int32 i = 0; i < charCount; i++) {
float charWidth = escapementArray[i] * fontSize;
if (totalWidth + charWidth > width) {
while (totalWidth + ellipsisWidth > width) {
if (i-- == 0) {
string.Truncate(0);
return;
}
totalWidth -= escapementArray[i] * fontSize;
}
string.RemoveChars(i, charCount - i);
string.AppendChars(B_UTF8_ELLIPSIS, 1);
return;
}
totalWidth += charWidth;
}
break;
}
case B_TRUNCATE_MIDDLE:
case B_TRUNCATE_SMART:
{
float leftWidth = 0;
float rightWidth = 0;
int32 leftIndex = 0;
int32 rightIndex = charCount - 1;
bool left = true;
for (int32 i = 0; i < charCount; i++) {
float charWidth
= escapementArray[left ? leftIndex : rightIndex] * fontSize;
if (leftWidth + rightWidth + charWidth > width) {
while (leftWidth + rightWidth + ellipsisWidth > width) {
if (leftIndex == 0 && rightIndex == charCount - 1) {
string.Truncate(0);
return;
}
if (leftIndex > 0 && (rightIndex == charCount - 1
|| leftWidth > rightWidth)) {
leftWidth -= escapementArray[--leftIndex]
* fontSize;
} else {
rightWidth -= escapementArray[++rightIndex]
* fontSize;
}
}
string.RemoveChars(leftIndex, rightIndex + 1 - leftIndex);
string.InsertChars(B_UTF8_ELLIPSIS, 1, leftIndex);
return;
}
if (left) {
leftIndex++;
leftWidth += charWidth;
} else {
rightIndex--;
rightWidth += charWidth;
}
left = rightWidth > leftWidth;
}
break;
}
}
}