- refresh dark theme + add some common source code from qbreak app
140
client/platforms/linux/autostart.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
#include "autostart.h"
|
||||
#include <QDebug>
|
||||
|
||||
#if defined(TARGET_LINUX)
|
||||
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <QFile>
|
||||
#include <QSettings>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
#define QBREAK_DESKTOP_NAME "qbreak.desktop"
|
||||
|
||||
static std::string read_desktop_file()
|
||||
{
|
||||
QFile f(":/assets/misc/qbreak.desktop");
|
||||
f.open(QFile::ReadOnly);
|
||||
auto bytes = f.readAll();
|
||||
return bytes.toStdString();
|
||||
}
|
||||
|
||||
static std::string fixup_desktop_file(const std::string& desktop_unit, const std::string& path)
|
||||
{
|
||||
// load set with first file
|
||||
std::istringstream inf(desktop_unit);
|
||||
std::vector<std::string> lines;
|
||||
std::string line;
|
||||
for (unsigned int i=0; std::getline(inf,line); i++)
|
||||
{
|
||||
if (line.find("Exec=") == 0)
|
||||
{
|
||||
line = "Exec=" + path;
|
||||
}
|
||||
lines.push_back(line);
|
||||
}
|
||||
|
||||
std::ostringstream oss;
|
||||
std::copy(lines.begin(), lines.end(), std::ostream_iterator<std::string>(oss, "\n"));
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
static fs::path home_dir()
|
||||
{
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
return pw ? pw->pw_dir : std::string();
|
||||
}
|
||||
|
||||
static fs::path autostart_dir()
|
||||
{
|
||||
return home_dir() / ".config" / "autostart";
|
||||
}
|
||||
|
||||
static fs::path autostart_path()
|
||||
{
|
||||
return autostart_dir() / QBREAK_DESKTOP_NAME;
|
||||
}
|
||||
|
||||
void autostart::enable(const std::string& path_to_me)
|
||||
{
|
||||
// Put .desktop file to ~/.config/autostart
|
||||
std::ofstream ofs(autostart_path());
|
||||
if (ofs.is_open())
|
||||
{
|
||||
ofs << fixup_desktop_file(read_desktop_file(), path_to_me);
|
||||
ofs.close();
|
||||
}
|
||||
else
|
||||
qDebug() << "Failed to write the desktop entry into autostart dir. Error: " << errno;
|
||||
}
|
||||
|
||||
void autostart::disable()
|
||||
{
|
||||
// Remove .desktop file from ~/.config/autostart
|
||||
::remove(autostart_path().c_str());
|
||||
}
|
||||
|
||||
bool autostart::is_enabled()
|
||||
{
|
||||
return fs::exists(fs::path(autostart_path()));
|
||||
}
|
||||
|
||||
// ----- appmenu -----
|
||||
static fs::path appmenu_install_dir()
|
||||
{
|
||||
// Global one
|
||||
// return fs::path("/usr/share/applications");
|
||||
|
||||
// User only
|
||||
return home_dir() / ".local" / "share" / "applications";
|
||||
}
|
||||
|
||||
void appmenu::install(const std::string& path_to_me)
|
||||
{
|
||||
// Put .desktop file to ~/.config/autostart
|
||||
std::ofstream ofs(appmenu_install_dir() / QBREAK_DESKTOP_NAME);
|
||||
if (ofs.is_open())
|
||||
{
|
||||
ofs << fixup_desktop_file(read_desktop_file(), path_to_me);
|
||||
ofs.close();
|
||||
}
|
||||
else
|
||||
qDebug() << "Failed to write the desktop entry into app menu dir. Error: " << errno;
|
||||
|
||||
// Install latest icons
|
||||
{
|
||||
auto icons = {"16x16", "32x32", "64x64", "128x128", "512x512"};
|
||||
|
||||
// Here Qt part
|
||||
auto target_dir = QFileInfo(QDir::homePath() + "/.local/share/icons/hicolor").absoluteFilePath();
|
||||
if (QFileInfo::exists(target_dir))
|
||||
{
|
||||
// Copy icons from resources
|
||||
for (auto& icon_suffix: icons)
|
||||
{
|
||||
QString icon_src = QString(":/assets/images/coffee_cup/icon_") + icon_suffix + ".png",
|
||||
icon_dst = target_dir + "/" + icon_suffix + "/apps/qbreak.png";
|
||||
QFile::copy(icon_src, icon_dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void appmenu::uninstall()
|
||||
{
|
||||
if (is_installed())
|
||||
fs::remove(appmenu_install_dir() / QBREAK_DESKTOP_NAME);
|
||||
}
|
||||
|
||||
bool appmenu::is_installed()
|
||||
{
|
||||
return fs::exists(appmenu_install_dir() / QBREAK_DESKTOP_NAME);
|
||||
}
|
||||
#endif
|
||||
22
client/platforms/linux/autostart.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef AUTOSTART_H
|
||||
#define AUTOSTART_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class autostart
|
||||
{
|
||||
public:
|
||||
static void enable(const std::string& path_to_me);
|
||||
static void disable();
|
||||
static bool is_enabled();
|
||||
};
|
||||
|
||||
class appmenu
|
||||
{
|
||||
public:
|
||||
static void install(const std::string& path_to_me);
|
||||
static void uninstall();
|
||||
static bool is_installed();
|
||||
};
|
||||
|
||||
#endif // AUTOSTART_H
|
||||
289
client/platforms/linux/idle_tracking.cpp
Normal file
@ -0,0 +1,289 @@
|
||||
#include "idle_tracking.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#if defined(TARGET_LINUX)
|
||||
|
||||
#include <QObject>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusReply>
|
||||
#include <QDBusInterface>
|
||||
|
||||
// Thanks to https://stackoverflow.com/questions/222606/detecting-keyboard-mouse-activity-in-linux
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
// This requires sudo apt install libxss-dev
|
||||
#include <X11/extensions/scrnsaver.h> // This can require libxss-dev to be installed
|
||||
#include <dlfcn.h>
|
||||
// #include <qmetatype.h>
|
||||
// #include <QDBusConnection>
|
||||
|
||||
/*
|
||||
// Prototype from stackoverflow
|
||||
int get_idle_time()
|
||||
{
|
||||
time_t idle_time;
|
||||
static XScreenSaverInfo *mit_info;
|
||||
Display *display;
|
||||
int screen;
|
||||
|
||||
mit_info = XScreenSaverAllocInfo();
|
||||
if ((display = XOpenDisplay(NULL)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
screen = DefaultScreen(display);
|
||||
XScreenSaverQueryInfo(display, RootWindow(display, screen), mit_info);
|
||||
idle_time = (mit_info->idle);
|
||||
XFree(mit_info);
|
||||
XCloseDisplay(display);
|
||||
|
||||
return idle_time;
|
||||
}
|
||||
*/
|
||||
|
||||
int get_idle_time_x11()
|
||||
{
|
||||
void* lib_xss = dlopen("libXss.so", RTLD_LAZY);
|
||||
if (!lib_xss)
|
||||
return 0;
|
||||
|
||||
void* lib_x11 = dlopen("libX11.so", RTLD_LAZY);
|
||||
if (!lib_x11)
|
||||
return 0;
|
||||
|
||||
typedef XScreenSaverInfo* (*xss_alloc_info)(void);
|
||||
xss_alloc_info alloc_info = (xss_alloc_info)dlsym(lib_xss, "XScreenSaverAllocInfo");
|
||||
|
||||
typedef Display* (*x11_open_display)(void*);
|
||||
x11_open_display open_display = (x11_open_display)dlsym(lib_x11, "XOpenDisplay");
|
||||
|
||||
|
||||
typedef Status (*xss_query_info)( Display* /* display */,
|
||||
Drawable /* drawable */,
|
||||
XScreenSaverInfo* /* info */);
|
||||
xss_query_info query_info = (xss_query_info)dlsym(lib_xss, "XScreenSaverQueryInfo");
|
||||
|
||||
typedef int (*x11_free)(void*);
|
||||
x11_free free_mem = (x11_free)dlsym(lib_x11, "XFree");
|
||||
|
||||
typedef int (*x11_close_display)(Display* display);
|
||||
x11_close_display close_display = (x11_close_display)dlsym(lib_x11, "XCloseDisplay");
|
||||
|
||||
|
||||
time_t idle_time;
|
||||
static XScreenSaverInfo *mit_info;
|
||||
Display *display;
|
||||
int screen;
|
||||
|
||||
mit_info = alloc_info();
|
||||
if ((display = open_display(NULL)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
screen = DefaultScreen(display);
|
||||
query_info(display, RootWindow(display, screen), mit_info);
|
||||
idle_time = (mit_info->idle);
|
||||
free_mem(mit_info);
|
||||
close_display(display);
|
||||
|
||||
dlclose(lib_xss);
|
||||
dlclose(lib_x11);
|
||||
return idle_time;
|
||||
}
|
||||
|
||||
int get_idle_time_gnome()
|
||||
{
|
||||
auto bus = QDBusConnection::sessionBus();
|
||||
if (!bus.isConnected())
|
||||
return 0;
|
||||
|
||||
QDBusInterface interface( "org.gnome.Mutter.IdleMonitor",
|
||||
"/org/gnome/Mutter/IdleMonitor/Core",
|
||||
"org.gnome.Mutter.IdleMonitor");
|
||||
|
||||
QDBusReply<int> reply = interface.call("GetIdletime");
|
||||
|
||||
return reply.isValid() ? reply.value() : 0;
|
||||
}
|
||||
|
||||
#if defined(USE_WAYLAND)
|
||||
#include <wayland-client-protocol-unstable.hpp>
|
||||
|
||||
class kde_idle_detector
|
||||
{
|
||||
private:
|
||||
wayland::seat_t seat;
|
||||
wayland::display_t d;
|
||||
wayland::org_kde_kwin_idle_t idle;
|
||||
wayland::org_kde_kwin_idle_timeout_t idle_timer;
|
||||
|
||||
uint64_t idle_start = 0;
|
||||
uint64_t idle_finish = 0;
|
||||
bool active = false;
|
||||
|
||||
public:
|
||||
kde_idle_detector()
|
||||
{}
|
||||
~kde_idle_detector()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
// Idle timeout is in msec
|
||||
void start(int idle_timeout)
|
||||
{
|
||||
if (active)
|
||||
return;
|
||||
|
||||
auto registry = d.get_registry();
|
||||
registry.on_global() = [&] (uint32_t name, const std::string& interface, uint32_t version)
|
||||
{
|
||||
if (interface == wayland::seat_t::interface_name)
|
||||
registry.bind(name, this->seat, version);
|
||||
else
|
||||
if (interface == wayland::org_kde_kwin_idle_t::interface_name)
|
||||
registry.bind(name, this->idle, version);
|
||||
};
|
||||
d.roundtrip();
|
||||
|
||||
|
||||
bool has_keyboard = false, has_pointer = false;
|
||||
seat.on_capabilities() = [&] (const wayland::seat_capability& capability)
|
||||
{
|
||||
has_keyboard = capability & wayland::seat_capability::keyboard;
|
||||
has_pointer = capability & wayland::seat_capability::pointer;
|
||||
};
|
||||
d.roundtrip();
|
||||
|
||||
idle_timer = idle.get_idle_timeout(seat, idle_timeout);
|
||||
idle_timer.on_idle() = [&]()
|
||||
{
|
||||
idle_start = ::time(nullptr);
|
||||
};
|
||||
|
||||
idle_timer.on_resumed() = [&]()
|
||||
{
|
||||
idle_finish = ::time(nullptr);
|
||||
};
|
||||
|
||||
active = true;
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
if (!active)
|
||||
return;
|
||||
|
||||
active = false;
|
||||
idle_timer.release();
|
||||
seat.release();
|
||||
}
|
||||
|
||||
// Return idle time in microseconds
|
||||
int get_idle_time() const
|
||||
{
|
||||
if (idle_start > idle_finish)
|
||||
{
|
||||
return (::time(nullptr) - idle_start) * 1000;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
kde_idle_detector kde_idle;
|
||||
int get_idle_time_kde_wayland()
|
||||
{
|
||||
// Ensure idle detector runs
|
||||
kde_idle.start(1);
|
||||
|
||||
return kde_idle.get_idle_time();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int get_idle_time_dynamically()
|
||||
{
|
||||
const char* wl_display = std::getenv("WAYLAND_DISPLAY");
|
||||
// const char* x11_display = std::getenv("DISPLAY");
|
||||
|
||||
#if defined(USE_WAYLAND)
|
||||
if (wl_display)
|
||||
{
|
||||
const char* desktop_name = std::getenv("XDG_SESSION_DESKTOP");
|
||||
if (!desktop_name)
|
||||
return 0;
|
||||
|
||||
if (strcmp(desktop_name, "KDE") == 0)
|
||||
return get_idle_time_kde_wayland();
|
||||
else
|
||||
if (strcmp(desktop_name, "GNOME") == 0)
|
||||
return get_idle_time_gnome();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return get_idle_time_x11();
|
||||
#else
|
||||
// Restrict to X11
|
||||
if (wl_display)
|
||||
return 0;
|
||||
|
||||
return get_idle_time_x11();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_WINDOWS)
|
||||
|
||||
// To handle Windows case later
|
||||
// https://stackoverflow.com/questions/8820615/how-to-check-in-c-if-the-system-is-active
|
||||
|
||||
/*
|
||||
#define WINDOWS_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <iostream>
|
||||
|
||||
// do something after 10 minutes of user inactivity
|
||||
static const unsigned int idle_milliseconds = 60*10*1000;
|
||||
// wait at least an hour between two runs
|
||||
static const unsigned int interval = 60*60*1000;
|
||||
|
||||
int main() {
|
||||
LASTINPUTINFO last_input;
|
||||
BOOL screensaver_active;
|
||||
|
||||
// main loop to check if user has been idle long enough
|
||||
for (;;) {
|
||||
if ( !GetLastInputInfo(&last_input)
|
||||
|| !SystemParametersInfo(SPI_GETSCREENSAVERACTIVE, 0,
|
||||
&screensaver_active, 0))
|
||||
{
|
||||
std::cerr << "WinAPI failed!" << std::endl;
|
||||
return ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (last_input.dwTime < idle_milliseconds && !screensaver_active) {
|
||||
// user hasn't been idle for long enough
|
||||
// AND no screensaver is running
|
||||
Sleep(1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
// user has been idle at least 10 minutes
|
||||
do_something();
|
||||
// done. Wait before doing the next loop.
|
||||
Sleep(interval);
|
||||
}
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
7
client/platforms/linux/idle_tracking.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef __IDLE_TRACKING_H
|
||||
#define __IDLE_TRACKING_H
|
||||
|
||||
// Returns the idle time in milliseconds
|
||||
extern int get_idle_time();
|
||||
extern int get_idle_time_dynamically();
|
||||
#endif
|
||||
|
Before Width: | Height: | Size: 522 B After Width: | Height: | Size: 522 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 546 B After Width: | Height: | Size: 546 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 523 B After Width: | Height: | Size: 523 B |
|
Before Width: | Height: | Size: 992 B After Width: | Height: | Size: 992 B |
|
Before Width: | Height: | Size: 567 B After Width: | Height: | Size: 567 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 558 B After Width: | Height: | Size: 558 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 557 B After Width: | Height: | Size: 557 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 551 B After Width: | Height: | Size: 551 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 574 B After Width: | Height: | Size: 574 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 546 B After Width: | Height: | Size: 546 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 545 B After Width: | Height: | Size: 545 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 541 B After Width: | Height: | Size: 541 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 574 B After Width: | Height: | Size: 574 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 525 B After Width: | Height: | Size: 525 B |
|
Before Width: | Height: | Size: 1008 B After Width: | Height: | Size: 1008 B |
|
Before Width: | Height: | Size: 549 B After Width: | Height: | Size: 549 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 532 B After Width: | Height: | Size: 532 B |
|
Before Width: | Height: | Size: 990 B After Width: | Height: | Size: 990 B |
|
Before Width: | Height: | Size: 554 B After Width: | Height: | Size: 554 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 397 B After Width: | Height: | Size: 397 B |
|
Before Width: | Height: | Size: 824 B After Width: | Height: | Size: 824 B |
|
Before Width: | Height: | Size: 426 B After Width: | Height: | Size: 426 B |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 862 B |
|
Before Width: | Height: | Size: 395 B After Width: | Height: | Size: 395 B |
|
Before Width: | Height: | Size: 810 B After Width: | Height: | Size: 810 B |
|
Before Width: | Height: | Size: 415 B After Width: | Height: | Size: 415 B |
|
Before Width: | Height: | Size: 867 B After Width: | Height: | Size: 867 B |
|
Before Width: | Height: | Size: 151 B After Width: | Height: | Size: 151 B |
|
Before Width: | Height: | Size: 205 B After Width: | Height: | Size: 205 B |
|
Before Width: | Height: | Size: 152 B After Width: | Height: | Size: 152 B |
|
Before Width: | Height: | Size: 205 B After Width: | Height: | Size: 205 B |
|
Before Width: | Height: | Size: 149 B After Width: | Height: | Size: 149 B |
|
Before Width: | Height: | Size: 203 B After Width: | Height: | Size: 203 B |
|
Before Width: | Height: | Size: 152 B After Width: | Height: | Size: 152 B |
|
Before Width: | Height: | Size: 204 B After Width: | Height: | Size: 204 B |
|
Before Width: | Height: | Size: 133 B After Width: | Height: | Size: 133 B |
|
Before Width: | Height: | Size: 238 B After Width: | Height: | Size: 238 B |
|
Before Width: | Height: | Size: 135 B After Width: | Height: | Size: 135 B |
|
Before Width: | Height: | Size: 240 B After Width: | Height: | Size: 240 B |
|
Before Width: | Height: | Size: 134 B After Width: | Height: | Size: 134 B |
|
Before Width: | Height: | Size: 238 B After Width: | Height: | Size: 238 B |
|
Before Width: | Height: | Size: 135 B After Width: | Height: | Size: 135 B |
|
Before Width: | Height: | Size: 239 B After Width: | Height: | Size: 239 B |
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 166 B |
|
Before Width: | Height: | Size: 260 B After Width: | Height: | Size: 260 B |
|
Before Width: | Height: | Size: 167 B After Width: | Height: | Size: 167 B |
|
Before Width: | Height: | Size: 263 B After Width: | Height: | Size: 263 B |
|
Before Width: | Height: | Size: 164 B After Width: | Height: | Size: 164 B |
|
Before Width: | Height: | Size: 260 B After Width: | Height: | Size: 260 B |
|
Before Width: | Height: | Size: 161 B After Width: | Height: | Size: 161 B |
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B |
|
Before Width: | Height: | Size: 404 B After Width: | Height: | Size: 404 B |
|
Before Width: | Height: | Size: 813 B After Width: | Height: | Size: 813 B |
|
Before Width: | Height: | Size: 422 B After Width: | Height: | Size: 422 B |
|
Before Width: | Height: | Size: 872 B After Width: | Height: | Size: 872 B |
|
Before Width: | Height: | Size: 396 B After Width: | Height: | Size: 396 B |
|
Before Width: | Height: | Size: 791 B After Width: | Height: | Size: 791 B |
|
Before Width: | Height: | Size: 421 B After Width: | Height: | Size: 421 B |
|
Before Width: | Height: | Size: 860 B After Width: | Height: | Size: 860 B |
|
Before Width: | Height: | Size: 650 B After Width: | Height: | Size: 650 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 731 B After Width: | Height: | Size: 731 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 655 B After Width: | Height: | Size: 655 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 704 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 476 B After Width: | Height: | Size: 476 B |
|
Before Width: | Height: | Size: 955 B After Width: | Height: | Size: 955 B |
|
Before Width: | Height: | Size: 545 B After Width: | Height: | Size: 545 B |
|
Before Width: | Height: | Size: 1003 B After Width: | Height: | Size: 1003 B |
|
Before Width: | Height: | Size: 466 B After Width: | Height: | Size: 466 B |
|
Before Width: | Height: | Size: 930 B After Width: | Height: | Size: 930 B |
|
Before Width: | Height: | Size: 518 B After Width: | Height: | Size: 518 B |
|
Before Width: | Height: | Size: 995 B After Width: | Height: | Size: 995 B |