Merge remote-tracking branch 'origin/master' into barview

This commit is contained in:
Dave Davenport 2017-06-01 14:20:36 +02:00
commit cdc8e462b8
35 changed files with 912 additions and 989 deletions

View File

@ -63,7 +63,7 @@ SOURCES=\
source/widgets/listview.c\
source/widgets/scrollbar.c\
source/xrmoptions.c\
source/x11-helper.c\
source/xcb.c\
source/css-colors.c\
source/dialogs/run.c\
source/dialogs/ssh.c\
@ -248,6 +248,7 @@ endif
history_test_CFLAGS=\
$(AM_CFLAGS)\
$(glib_CFLAGS)\
$(NKUTILS_CFLAGS)\
$(libsn_CFLAGS)\
$(cairo_CFLAGS)\
-DTHEME_DIR=\"$(themedir)\"\
@ -257,7 +258,8 @@ history_test_CFLAGS=\
-I$(top_builddir)/
history_test_LDADD=\
$(glib_LIBS)
$(glib_LIBS)\
$(NKUTILS_LIBS)
history_test_SOURCES=\
@ -274,6 +276,7 @@ textbox_test_CFLAGS=\
$(AM_CFLAGS)\
$(glib_CFLAGS)\
$(pango_CFLAGS)\
$(NKUTILS_CFLAGS)\
$(GW_XCB_CFLAGS)\
$(cairo_CFLAGS)\
$(libsn_CFLAGS)\
@ -289,6 +292,7 @@ textbox_test_CFLAGS=\
textbox_test_LDADD=\
$(glib_LIBS)\
$(pango_LIBS)\
$(NKUTILS_LIBS)\
$(GW_XCB_LIBS)\
$(cairo_LIBS)\
$(librsvg_LIBS)\
@ -306,8 +310,6 @@ helper_pidfile_SOURCES=\
include/helper-theme.h\
include/xrmoptions.h\
source/xrmoptions.c\
source/x11-helper.c\
include/x11-helper.h\
test/helper-pidfile.c
helper_tokenize_CFLAGS=$(textbox_test_CFLAGS)
@ -322,8 +324,6 @@ helper_tokenize_SOURCES=\
include/helper-theme.h\
include/xrmoptions.h\
source/xrmoptions.c\
source/x11-helper.c\
include/x11-helper.h\
test/helper-tokenize.c
widget_test_LDADD=$(textbox_test_LDADD)
@ -334,7 +334,6 @@ widget_test_SOURCES=\
source/theme.c\
source/css-colors.c\
source/helper.c\
source/x11-helper.c\
config/config.c\
lexer/theme-parser.y\
lexer/theme-lexer.l\
@ -374,7 +373,6 @@ textbox_test_SOURCES=\
source/theme.c\
source/css-colors.c\
source/helper.c\
source/x11-helper.c\
config/config.c\
include/keyb.h\
include/rofi.h\
@ -404,7 +402,6 @@ theme_parser_test_SOURCES=\
include/css-colors.h\
include/xrmoptions.h\
source/xrmoptions.c\
source/x11-helper.c\
lexer/theme-lexer.c\
lexer/theme-parser.c\
lexer/theme-parser.h\
@ -423,7 +420,6 @@ helper_test_SOURCES=\
include/helper-theme.h\
include/xrmoptions.h\
source/xrmoptions.c\
source/x11-helper.c\
test/helper-test.c
@ -431,6 +427,7 @@ helper_test_CFLAGS=\
$(AM_CFLAGS)\
$(glib_CFLAGS)\
$(pango_CFLAGS)\
$(NKUTILS_CFLAGS)\
$(GW_XCB_CFLAGS)\
$(cairo_CFLAGS)\
$(librsvg_CFLAGS)\
@ -446,6 +443,7 @@ helper_test_CFLAGS=\
helper_test_LDADD=\
$(glib_LIBS)\
$(pango_LIBS)\
$(NKUTILS_LIBS)\
$(GW_XCB_LIBS)\
$(libsn_LIBS)\
$(librsvg_LIBS)\
@ -462,7 +460,6 @@ helper_expand_SOURCES=\
include/helper-theme.h\
include/xrmoptions.h\
source/xrmoptions.c\
source/x11-helper.c\
test/helper-expand.c
helper_expand_CFLAGS=${helper_test_CFLAGS}
@ -482,7 +479,6 @@ helper_config_cmdline_parser_SOURCES=\
include/helper-theme.h\
include/xrmoptions.h\
source/xrmoptions.c\
source/x11-helper.c\
test/helper-config-cmdline-parser.c

View File

@ -16,6 +16,8 @@ rofi.yoffset: -2
rofi.xoffset: 0
! "Always show number of lines" Set from: File
rofi.fixed-num-lines: true
! "Whether to load and show icons" Set from: Default
! rofi.show-icons: false
! "Terminal to use" Set from: File
rofi.terminal: sakura
! "Ssh client to use" Set from: File
@ -30,6 +32,8 @@ rofi.run-command: bash -c "{cmd}"
rofi.run-shell-command: {terminal} -e {cmd}
! "Command executed on accep-entry-custom for window modus" Set from: File
rofi.window-command: xkill -id {window}
! "Theme to use to look for icons" Set from: Default
! rofi.drun-icon-theme: gnome
! "Disable history in run/ssh" Set from: File
rofi.disable-history: false
! "Use sorting" Set from: Default

View File

@ -27,6 +27,9 @@
#ifndef ROFI_HELPER_H
#define ROFI_HELPER_H
#include <cairo.h>
/**
* @defgroup HELPERS Helpers
*/
@ -265,4 +268,14 @@ int utf8_strncmp ( const char *a, const char* b, size_t n ) __attribute__( ( non
* @returns FALSE On failure, TRUE on success
*/
int helper_execute_command ( const char *wd, const char *cmd, int run_in_term );
/**
* @param file The file path
* @param height The wanted height
* Gets a surface from an svg path
*
* @returns a cairo surface from an svg path
*/
cairo_surface_t *cairo_image_surface_create_from_svg ( const gchar* file, int height );
#endif // ROFI_HELPER_H

View File

@ -77,6 +77,8 @@ void rofi_add_error_message ( GString *str );
*/
void rofi_set_return_code ( int code );
void rofi_quit_main_loop ( void );
/**
* @param name Search for mode with this name.
*

View File

@ -33,7 +33,7 @@
#include "widgets/listview.h"
#include "widgets/box.h"
#include "keyb.h"
#include "x11-helper.h"
#include "xcb.h"
#include "theme.h"
/**

View File

@ -28,7 +28,6 @@
#ifndef ROFI_VIEW_H
#define ROFI_VIEW_H
#include "mode.h"
#include "xkb.h"
/**
* @defgroup View View
@ -94,12 +93,33 @@ MenuReturn rofi_view_get_return_value ( const RofiViewState *state );
unsigned int rofi_view_get_next_position ( const RofiViewState *state );
/**
* @param state the Menu handle
* @param event the event to handle
* @param xkb the keyboard handle
* @param text The text to add to the input box
*
* Process an Xevent.
* Update the state if needed.
*/
void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, xkb_stuff *xkb );
void rofi_view_handle_text ( RofiViewState *state, char *text );
/**
* @param state the Menu handle
* @param x The X coordinates of the motion
* @param x The Y coordinates of the motion
*
* Update the state if needed.
*/
void rofi_view_handle_mouse_motion( RofiViewState *state, gint x, gint y );
/**
* @param state the Menu handle
*
* Update the state if needed.
*/
void rofi_view_maybe_update ( RofiViewState *state );
void rofi_view_temp_configure_notify ( RofiViewState *state, xcb_configure_notify_event_t *xce );
void rofi_view_temp_click_to_exit ( RofiViewState *state, xcb_window_t target );
/**
* @param state the Menu handle
*
* Update the state if needed.
*/
void rofi_view_frame_callback ( void );
/**
* @param state the Menu handle
*

View File

@ -35,7 +35,6 @@
#include <cairo.h>
#include "widgets/widget.h"
#include "widgets/widget-internal.h"
#include "x11-helper.h"
#include "keyb.h"
/**
@ -88,7 +87,7 @@ typedef enum
TB_WRAP = 1 << 21,
TB_PASSWORD = 1 << 22,
TB_INDICATOR = 1 << 23,
TB_ICON = 1<<24,
TB_ICON = 1 << 24,
} TextboxFlags;
/**
* Flags indicating current state of the textbox.
@ -173,7 +172,7 @@ int textbox_keybinding ( textbox *tb, KeyBindingAction action );
* The text should be one insert from a keypress.. the first gunichar is validated to be (or not) control
* return TRUE if inserted
*/
gboolean textbox_append_char ( textbox *tb, const char *pad, const int pad_len );
gboolean textbox_append_text ( textbox *tb, const char *pad, const int pad_len );
/**
* @param tb Handle to the textbox

View File

@ -1,268 +0,0 @@
/*
* rofi
*
* MIT/X11 License
* Copyright © 2013-2017 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef X11_ROFI_HELPER_H
#define X11_ROFI_HELPER_H
#include <glib.h>
#include <cairo.h>
#include <librsvg/rsvg.h>
#include <xcb/xcb.h>
#include <xkbcommon/xkbcommon.h>
#include "xkb.h"
/**
* @defgroup X11Helper X11Helper
* @ingroup HELPERS
* @{
*/
/**
* @param w The xcb_window_t to read property from.
* @param atom The property identifier
*
* Get text property defined by atom from window.
* Support utf8.
*
* @returns a newly allocated string with the result or NULL
*/
char* window_get_text_prop ( xcb_window_t w, xcb_atom_t atom );
/**
* @param w The xcb_window_t to set property on
* @param prop Atom of the property to change
* @param atoms List of atoms to change the property too
* @param count The length of the atoms list.
*
* Set property on window.
*/
void window_set_atom_prop ( xcb_window_t w, xcb_atom_t prop, xcb_atom_t *atoms, int count );
/** For getting the atoms in an enum */
#define ATOM_ENUM( x ) x
/** Get the atoms as strings. */
#define ATOM_CHAR( x ) # x
/** Atoms we want to pre-load */
#define EWMH_ATOMS( X ) \
X ( _NET_WM_WINDOW_OPACITY ), \
X ( I3_SOCKET_PATH ), \
X ( UTF8_STRING ), \
X ( STRING ), \
X ( CLIPBOARD ), \
X ( WM_WINDOW_ROLE ), \
X ( _XROOTPMAP_ID ), \
X ( _MOTIF_WM_HINTS ), \
X ( ESETROOT_PMAP_ID )
/** enumeration of the atoms. */
enum { EWMH_ATOMS ( ATOM_ENUM ), NUM_NETATOMS };
/** atoms as string */
extern const char *netatom_names[];
/** atoms */
extern xcb_atom_t netatoms[NUM_NETATOMS];
/**
* Enumerator describing the different modifier keys.
*/
enum
{
/** Shift key */
X11MOD_SHIFT,
/** Control Key */
X11MOD_CONTROL,
/** Alt key */
X11MOD_ALT,
/** Meta key */
X11MOD_META,
/** Super (window) key */
X11MOD_SUPER,
/** Hyper key */
X11MOD_HYPER,
/** Any modifier */
X11MOD_ANY,
/** Number of modifier keys */
NUM_X11MOD
};
/**
* Structure describing a workarea/monitor.
*/
typedef struct _workarea
{
/** numeric monitor id. */
int monitor_id;
/** if monitor is set as primary monitor. */
int primary;
/** Horizontal location (in pixels) of the monitor. */
int x;
/** Vertical location (in pixels) of the monitor. */
int y;
/** Width of the monitor. */
int w;
/** Height of the monitor */
int h;
int mw, mh;
/** Output name of the monitor, e.g. eDP1 or VGA-1 */
char *name;
/** Pointer to next monitor */
struct _workarea *next;
} workarea;
/**
* @param mon workarea to be filled in.
*
* Fills in #mon with the information about the monitor rofi should show on.
*
* @returns TRUE if monitor is found, FALSE if no monitor could be detected.
*/
int monitor_active ( workarea *mon );
/**
* Release keyboard grab on root window.
*/
void release_keyboard ( void );
/**
* Release pointer grab on root window.
*/
void release_pointer ( void );
/**
* @param w xcb_window_t we want to grab keyboard on.
* @param iters Number of retries.
*
* Grab keyboard.
*
* @return 1 when keyboard is grabbed, 0 not.
*/
int take_keyboard ( xcb_window_t w, int iters );
/**
* @param w xcb_window_t we want to grab mouse on.
* @param iters Number of retries.
*
* Grab mouse.
*
* @return 1 when mouse is grabbed, 0 not.
*/
int take_pointer ( xcb_window_t w, int iters );
/**
* Setup several items required.
* * Error handling,
* * Numlock detection
* * Cache
*/
void x11_setup ( void );
/**
* Depth of visual
*/
extern xcb_depth_t *depth;
/**
* Visual to use for creating window
*/
extern xcb_visualtype_t *visual;
/**
* Color map to use for creating window
*/
extern xcb_colormap_t map;
/**
* This function tries to create a 32bit TrueColor colormap.
* If this fails, it falls back to the default for the connected display.
*/
void x11_create_visual_and_colormap ( void );
/**
* Gets a surface containing the background image of the desktop.
*
* @returns a cairo surface with the background image of the desktop.
*/
cairo_surface_t * x11_helper_get_bg_surface ( void );
/**
* Gets a surface for the root window of the desktop.
*
* Can be used to take screenshot.
*
* @returns a cairo surface for the root window of the desktop.
*/
cairo_surface_t *x11_helper_get_screenshot_surface ( void );
/**
* Gets a surface from an svg path
*
* @returns a cairo surface from an svg path
*/
cairo_surface_t *cairo_image_surface_create_from_svg ( const gchar* file, int height );
/**
* Creates an internal represenation of the available monitors.
* Used for positioning rofi.
*/
void x11_build_monitor_layout ( void );
/**
* Dump the monitor layout to stdout.
*/
void x11_dump_monitor_layout ( void );
/**
* @param window The X11 window to modify
*
* Set the right hints to disable the window decoration.
* (Set MOTIF_WM_HINTS, decoration field)
*/
void x11_disable_decoration ( xcb_window_t window );
/**
* List of window managers that need different behaviour to functioning.
*/
typedef enum
{
/** Default EWHM compatible window manager */
WM_EWHM = 0,
/** I3 Window manager */
WM_I3 = 1,
/** Awesome window manager */
WM_AWESOME = 2,
/** Openbox window manager */
WM_OPENBOX = 4
} WindowManager;
/**
* Indicates the current window manager.
* This is used for work-arounds.
*/
extern WindowManager current_window_manager;
/**
* discover the window manager.
*/
void x11_helper_discover_window_manager ( void );
/*@}*/
#endif

View File

@ -33,12 +33,17 @@
#include <xcb/xcb.h>
#include <xcb/xcb_ewmh.h>
#include "libgwater-xcb.h"
#include "nkutils-bindings.h"
/**
* Structure to keep xcb stuff around.
*/
struct _xcb_stuff
{
GMainLoop *main_loop;
GWaterXcbSource *source;
xcb_connection_t *connection;
xcb_ewmh_connection_t ewmh;
xcb_screen_t *screen;
@ -46,6 +51,16 @@ struct _xcb_stuff
SnDisplay *sndisplay;
SnLauncheeContext *sncontext;
struct _workarea *monitors;
struct
{
/** Flag indicating first event */
uint8_t first_event;
/** Keyboard device id */
int32_t device_id;
} xkb;
NkBindings *bindings;
NkBindingsSeat *bindings_seat;
gboolean mouse_seen;
};
#endif

View File

@ -28,6 +28,9 @@
#ifndef ROFI_XCB_H
#define ROFI_XCB_H
#include <xcb/xcb.h>
#include <cairo.h>
/**
* xcb data structure type declaration.
*/
@ -45,11 +48,201 @@ extern xcb_stuff *xcb;
*
* @returns the root window.
*/
xcb_window_t xcb_stuff_get_root_window ( xcb_stuff *xcb );
xcb_window_t xcb_stuff_get_root_window ( void );
/**
* @param xcb The xcb data structure.
*
* Disconnect and free all xcb connections and references.
*/
void xcb_stuff_wipe ( xcb_stuff *xcb );
void xcb_stuff_wipe ( void );
/**
* @param w The xcb_window_t to read property from.
* @param atom The property identifier
*
* Get text property defined by atom from window.
* Support utf8.
*
* @returns a newly allocated string with the result or NULL
*/
char* window_get_text_prop ( xcb_window_t w, xcb_atom_t atom );
/**
* @param w The xcb_window_t to set property on
* @param prop Atom of the property to change
* @param atoms List of atoms to change the property too
* @param count The length of the atoms list.
*
* Set property on window.
*/
void window_set_atom_prop ( xcb_window_t w, xcb_atom_t prop, xcb_atom_t *atoms, int count );
/** For getting the atoms in an enum */
#define ATOM_ENUM( x ) x
/** Get the atoms as strings. */
#define ATOM_CHAR( x ) # x
/** Atoms we want to pre-load */
#define EWMH_ATOMS( X ) \
X ( _NET_WM_WINDOW_OPACITY ), \
X ( I3_SOCKET_PATH ), \
X ( UTF8_STRING ), \
X ( STRING ), \
X ( CLIPBOARD ), \
X ( WM_WINDOW_ROLE ), \
X ( _XROOTPMAP_ID ), \
X ( _MOTIF_WM_HINTS ), \
X ( ESETROOT_PMAP_ID )
/** enumeration of the atoms. */
enum { EWMH_ATOMS ( ATOM_ENUM ), NUM_NETATOMS };
/** atoms as string */
extern const char *netatom_names[];
/** atoms */
extern xcb_atom_t netatoms[NUM_NETATOMS];
/**
* Enumerator describing the different modifier keys.
*/
enum
{
/** Shift key */
X11MOD_SHIFT,
/** Control Key */
X11MOD_CONTROL,
/** Alt key */
X11MOD_ALT,
/** Meta key */
X11MOD_META,
/** Super (window) key */
X11MOD_SUPER,
/** Hyper key */
X11MOD_HYPER,
/** Any modifier */
X11MOD_ANY,
/** Number of modifier keys */
NUM_X11MOD
};
/**
* Structure describing a workarea/monitor.
*/
typedef struct _workarea
{
/** numeric monitor id. */
int monitor_id;
/** if monitor is set as primary monitor. */
int primary;
/** Horizontal location (in pixels) of the monitor. */
int x;
/** Vertical location (in pixels) of the monitor. */
int y;
/** Width of the monitor. */
int w;
/** Height of the monitor */
int h;
int mw, mh;
/** Output name of the monitor, e.g. eDP1 or VGA-1 */
char *name;
/** Pointer to next monitor */
struct _workarea *next;
} workarea;
/**
* @param mon workarea to be filled in.
*
* Fills in #mon with the information about the monitor rofi should show on.
*
* @returns TRUE if monitor is found, FALSE if no monitor could be detected.
*/
int monitor_active ( workarea *mon );
/**
* @param main_loop The GMainLoop
*
* Setup several items required.
* * Error handling,
* * Numlock detection
* * Cache
*
* @returns Whether the setup succeeded or not
*/
gboolean x11_setup ( GMainLoop *main_loop );
/**
* Depth of visual
*/
extern xcb_depth_t *depth;
/**
* Visual to use for creating window
*/
extern xcb_visualtype_t *visual;
/**
* Color map to use for creating window
*/
extern xcb_colormap_t map;
gboolean x11_late_setup ( void );
void x11_early_cleanup ( void );
/**
* Gets a surface containing the background image of the desktop.
*
* @returns a cairo surface with the background image of the desktop.
*/
cairo_surface_t * x11_helper_get_bg_surface ( void );
/**
* Gets a surface for the root window of the desktop.
*
* Can be used to take screenshot.
*
* @returns a cairo surface for the root window of the desktop.
*/
cairo_surface_t *x11_helper_get_screenshot_surface ( void );
/**
* Creates an internal represenation of the available monitors.
* Used for positioning rofi.
*/
void x11_build_monitor_layout ( void );
/**
* Dump the monitor layout to stdout.
*/
void x11_dump_monitor_layout ( void );
/**
* @param window The X11 window to modify
*
* Set the right hints to disable the window decoration.
* (Set MOTIF_WM_HINTS, decoration field)
*/
void x11_disable_decoration ( xcb_window_t window );
/**
* List of window managers that need different behaviour to functioning.
*/
typedef enum
{
/** Default EWHM compatible window manager */
WM_EWHM = 0,
/** I3 Window manager */
WM_I3 = 1,
/** Awesome window manager */
WM_AWESOME = 2,
/** Openbox window manager */
WM_OPENBOX = 4
} WindowManager;
/**
* Indicates the current window manager.
* This is used for work-arounds.
*/
extern WindowManager current_window_manager;
/**
* discover the window manager.
*/
void x11_helper_discover_window_manager ( void );
#endif

View File

@ -1,45 +0,0 @@
/*
* rofi
*
* MIT/X11 License
* Copyright © 2013-2017 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef ROFI_XKB_INTERNAL_H
#define ROFI_XKB_INTERNAL_H
#include "nkutils-bindings.h"
#include <xkbcommon/xkbcommon.h>
struct xkb_stuff
{
/** connection to the X server*/
xcb_connection_t *xcb_connection;
/** Flag indicating first event */
uint8_t first_event;
/** Keyboard device id */
int32_t device_id;
NkBindings *bindings;
};
#endif

View File

@ -1,35 +0,0 @@
/*
* rofi
*
* MIT/X11 License
* Copyright © 2013-2017 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef ROFI_XKB_H
#define ROFI_XKB_H
/**
* Structure holding xkb related state.
*/
typedef struct xkb_stuff xkb_stuff;
#endif

View File

@ -155,7 +155,7 @@ rofi_sources = files(
'source/widgets/listview.c',
'source/widgets/scrollbar.c',
'source/xrmoptions.c',
'source/x11-helper.c',
'source/xcb.c',
'source/dialogs/run.c',
'source/dialogs/ssh.c',
'source/dialogs/drun.c',
@ -188,7 +188,6 @@ rofi_sources = files(
'include/widgets/listview.h',
'include/widgets/scrollbar.h',
'include/xrmoptions.h',
'include/x11-helper.h',
'include/dialogs/ssh.h',
'include/dialogs/run.h',
'include/dialogs/drun.h',
@ -198,8 +197,6 @@ rofi_sources = files(
'include/dialogs/window.h',
'include/dialogs/dialogs.h',
'include/dialogs/help-keys.h',
'include/xkb.h',
'include/xkb-internal.h',
)
theme_lexer_sources = files('lexer/theme-lexer.l')
theme_parser_sources = files('lexer/theme-parser.y')
@ -266,7 +263,6 @@ test('helper_pidfile test', executable('helper_pidfile.test', [
'config/config.c',
'source/helper.c',
'source/xrmoptions.c',
'source/x11-helper.c',
]),
dependencies: deps,
))
@ -278,7 +274,6 @@ test('helper_tokenize test', executable('helper_tokenize.test', [
'config/config.c',
'source/helper.c',
'source/xrmoptions.c',
'source/x11-helper.c',
]),
dependencies: deps,
))
@ -294,7 +289,6 @@ test('widget test', executable('widget.test', [
'source/theme.c',
'source/css-colors.c',
'source/helper.c',
'source/x11-helper.c',
'config/config.c',
]),
dependencies: deps,
@ -341,7 +335,6 @@ test('textbox test', executable('textbox.test', [
'source/theme.c',
'source/css-colors.c',
'source/helper.c',
'source/x11-helper.c',
'config/config.c',
]),
dependencies: deps,
@ -354,7 +347,6 @@ test('helper test', executable('helper.test', [
'config/config.c',
'source/helper.c',
'source/xrmoptions.c',
'source/x11-helper.c',
]),
dependencies: deps,
))
@ -366,7 +358,6 @@ test('helper_expand test', executable('helper_expand.test', [
'config/config.c',
'source/helper.c',
'source/xrmoptions.c',
'source/x11-helper.c',
]),
dependencies: deps,
))
@ -378,7 +369,6 @@ test('helper_config_cmdline_parser test', executable('helper_config_cmdline_pars
'config/config.c',
'source/helper.c',
'source/xrmoptions.c',
'source/x11-helper.c',
]),
dependencies: deps,
))
@ -395,7 +385,6 @@ if check.found()
'config/config.c',
'source/helper.c',
'source/xrmoptions.c',
'source/x11-helper.c',
'source/theme.c',
'source/css-colors.c',
]),

View File

@ -50,6 +50,7 @@
#include "history.h"
#include "dialogs/drun.h"
#include "nkutils-xdg-theme.h"
#include "xcb.h"
#define DRUN_CACHE_FILE "rofi2.druncache"
@ -89,9 +90,9 @@ typedef struct
unsigned int cmd_list_length_actual;
unsigned int history_length;
// List of disabled entries.
GHashTable *disabled_entries;
unsigned int disabled_entries_length;
GThread *thread;
GHashTable *disabled_entries;
unsigned int disabled_entries_length;
GThread *thread;
} DRunModePrivateData;
struct RegexEvalArg
@ -423,41 +424,44 @@ static void drun_icon_fetch ( gpointer data )
{
// as long as dr->icon is updated atomicly.. (is a pointer write atomic?)
// this should be fine running in another thread.
GTimer *t = g_timer_new ();
DRunModePrivateData *pd = (DRunModePrivateData*)data;
for ( size_t i = 0; i < pd->cmd_list_length; i++ ) {
DRunModeEntry *dr = &( pd->entry_list[i] );
if ( dr->icon_name == NULL )
continue;
gchar *icon_path = nk_xdg_theme_get_icon ( pd->xdg_context, NULL, "Applications", dr->icon_name, 32, 1, TRUE );
if ( icon_path == NULL ) {
g_free(dr->icon_name);
dr->icon_name = NULL;
continue;
}
else
g_log ( G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Found Icon %s(%d): %s", dr->icon_name, 32, icon_path );
GTimer *t = g_timer_new ();
DRunModePrivateData *pd = (DRunModePrivateData *) data;
for ( size_t i = 0; i < pd->cmd_list_length; i++ ) {
DRunModeEntry *dr = &( pd->entry_list[i] );
if ( dr->icon_name == NULL ) {
continue;
}
gchar *icon_path = nk_xdg_theme_get_icon ( pd->xdg_context, NULL, "Applications", dr->icon_name, 32, 1, TRUE );
if ( icon_path == NULL ) {
g_free ( dr->icon_name );
dr->icon_name = NULL;
continue;
}
else{
g_log ( G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Found Icon %s(%d): %s", dr->icon_name, 32, icon_path );
}
if ( g_str_has_suffix ( icon_path, ".png" ) )
dr->icon = cairo_image_surface_create_from_png(icon_path);
else if ( g_str_has_suffix ( icon_path, ".svg" ) )
dr->icon = cairo_image_surface_create_from_svg(icon_path, 32);
else {
g_log ( G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Icon type not yet supported: %s", icon_path );
char *r = dr->icon_name;
dr->icon_name = NULL;
g_free(r);
}
g_free(icon_path);
// if ( (i%100) == 99 )
{
rofi_view_reload();
}
}
rofi_view_reload();
g_log ( G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "elapsed: %f\n" , g_timer_elapsed ( t, NULL));
g_timer_destroy ( t );
if ( g_str_has_suffix ( icon_path, ".png" ) ) {
dr->icon = cairo_image_surface_create_from_png ( icon_path );
}
else if ( g_str_has_suffix ( icon_path, ".svg" ) ) {
dr->icon = cairo_image_surface_create_from_svg ( icon_path, 32 );
}
else {
g_log ( G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Icon type not yet supported: %s", icon_path );
char *r = dr->icon_name;
dr->icon_name = NULL;
g_free ( r );
}
g_free ( icon_path );
// if ( (i%100) == 99 )
{
rofi_view_reload ();
}
}
rofi_view_reload ();
g_log ( G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "elapsed: %f\n", g_timer_elapsed ( t, NULL ) );
g_timer_destroy ( t );
}
static int drun_mode_init ( Mode *sw )
@ -531,7 +535,7 @@ static void drun_mode_destroy ( Mode *sw )
{
DRunModePrivateData *rmpd = (DRunModePrivateData *) mode_get_private_data ( sw );
if ( rmpd != NULL ) {
if ( rmpd->thread ){
if ( rmpd->thread ) {
g_thread_join ( rmpd->thread );
rmpd->thread = NULL;
}
@ -572,7 +576,7 @@ static cairo_surface_t *_get_icon ( const Mode *sw, unsigned int selected_line,
{
DRunModePrivateData *pd = (DRunModePrivateData *) mode_get_private_data ( sw );
g_return_val_if_fail ( pd->entry_list != NULL, NULL );
DRunModeEntry *dr = &( pd->entry_list[selected_line] );
DRunModeEntry *dr = &( pd->entry_list[selected_line] );
return dr->icon;
}

View File

@ -52,7 +52,6 @@
#include "settings.h"
#include "helper.h"
#include "widgets/textbox.h"
#include "x11-helper.h"
#include "dialogs/window.h"
#define WINLIST 32

View File

@ -43,14 +43,14 @@
#include <sys/stat.h>
#include <pwd.h>
#include <ctype.h>
#include <xcb/xcb.h>
#include <pango/pango.h>
#include <pango/pango-fontmap.h>
#include <pango/pangocairo.h>
#include <librsvg/rsvg.h>
#include "xcb.h"
#include "helper.h"
#include "helper-theme.h"
#include "settings.h"
#include "x11-helper.h"
#include "rofi.h"
#include "view.h"
@ -1024,3 +1024,27 @@ char *helper_get_theme_path ( const char *file )
}
return filename;
}
cairo_surface_t* cairo_image_surface_create_from_svg ( const gchar* file, int height )
{
cairo_surface_t *surface;
cairo_t *cr;
RsvgHandle * handle;
RsvgDimensionData dimensions;
handle = rsvg_handle_new_from_file ( file, NULL );
rsvg_handle_get_dimensions ( handle, &dimensions );
double scale = (double) height / dimensions.height;
surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32,
(double) dimensions.width * scale,
(double) dimensions.height * scale );
cr = cairo_create ( surface );
cairo_scale ( cr, scale, scale );
rsvg_handle_render_cairo ( handle, cr );
cairo_destroy ( cr );
rsvg_handle_close ( handle, NULL );
g_object_unref ( handle );
return surface;
}

View File

@ -28,8 +28,6 @@
#include <config.h>
#include <string.h>
#include "rofi.h"
#include "xkb.h"
#include "xkb-internal.h"
#include "nkutils-bindings.h"
#include "xrmoptions.h"
@ -140,7 +138,7 @@ void setup_abe ( void )
}
}
static gboolean binding_trigger_action ( guint scope, gpointer user_data )
static gboolean binding_trigger_action ( guint64 scope, gpointer user_data )
{
return rofi_view_trigger_action ( rofi_view_get_active (), scope, GPOINTER_TO_UINT ( user_data ) );
}

View File

@ -30,7 +30,6 @@
#include <string.h>
#include "rofi.h"
#include "xrmoptions.h"
#include "x11-helper.h"
#include "mode.h"
// This one should only be in mode implementations.

View File

@ -39,11 +39,6 @@
#include <locale.h>
#include <gmodule.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
#include <xcb/xcb_ewmh.h>
#include <xcb/xkb.h>
#include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-x11.h>
#include <sys/types.h>
#include <glib-unix.h>
@ -51,14 +46,12 @@
#include <libgwater-xcb.h>
#include "xcb-internal.h"
#include "xkb-internal.h"
#include "settings.h"
#include "mode.h"
#include "rofi.h"
#include "helper.h"
#include "widgets/textbox.h"
#include "x11-helper.h"
#include "xrmoptions.h"
#include "dialogs/dialogs.h"
@ -87,11 +80,6 @@ void rofi_add_error_message ( GString *str )
{
list_of_error_msgs = g_list_append ( list_of_error_msgs, str );
}
/** global structure holding the keyboard status */
struct xkb_stuff xkb = {
.xcb_connection = NULL,
.bindings = NULL,
};
/** Path to the configuration file */
G_MODULE_EXPORT char *config_path = NULL;
@ -109,8 +97,6 @@ unsigned int curr_switcher = 0;
/** Glib main loop. */
GMainLoop *main_loop = NULL;
/** GWater xcb source, signalling events from the X server */
GWaterXcbSource *main_loop_source = NULL;
/** Flag indicating we are in dmenu mode. */
static int dmenu_mode = FALSE;
@ -151,21 +137,6 @@ static int switcher_get ( const char *name )
return -1;
}
/**
* Do needed steps to start showing the gui
*/
static int setup ()
{
// Create pid file
int pfd = create_pid_file ( pidfile );
if ( pfd >= 0 ) {
// Request truecolor visual.
x11_create_visual_and_colormap ( );
textbox_setup ();
}
return pfd;
}
/**
* Teardown the gui.
*/
@ -175,9 +146,7 @@ static void teardown ( int pfd )
// Cleanup font setup.
textbox_cleanup ( );
// Release the window.
release_keyboard ( );
release_pointer ( );
x11_early_cleanup ();
// Cleanup view
rofi_view_cleanup ();
@ -426,18 +395,11 @@ static void cleanup ()
}
rofi_view_workers_finalize ();
if ( main_loop != NULL ) {
if ( main_loop_source ) {
g_water_xcb_source_free ( main_loop_source );
}
g_main_loop_unref ( main_loop );
main_loop = NULL;
}
// XKB Cleanup
//
nk_bindings_free ( xkb.bindings );
// Cleanup
xcb_stuff_wipe ( xcb );
xcb_stuff_wipe ();
// Cleaning up memory allocated by the Xresources file.
config_xresource_free ();
@ -629,74 +591,9 @@ static gboolean setup_modi ( void )
return FALSE;
}
/**
* Process X11 events in the main-loop (gui-thread) of the application.
*/
static void main_loop_x11_event_handler_view ( xcb_generic_event_t *ev )
void rofi_quit_main_loop ( void )
{
RofiViewState *state = rofi_view_get_active ();
if ( state != NULL ) {
rofi_view_itterrate ( state, ev, &xkb );
if ( rofi_view_get_completed ( state ) ) {
// This menu is done.
rofi_view_finalize ( state );
// cleanup
if ( rofi_view_get_active () == NULL ) {
g_main_loop_quit ( main_loop );
}
}
}
}
static gboolean main_loop_x11_event_handler ( xcb_generic_event_t *ev, G_GNUC_UNUSED gpointer data )
{
if ( ev == NULL ) {
int status = xcb_connection_has_error ( xcb->connection );
if ( status > 0 ) {
g_warning ( "The XCB connection to X server had a fatal error: %d", status );
g_main_loop_quit ( main_loop );
return G_SOURCE_REMOVE;
}
else {
g_warning ( "main_loop_x11_event_handler: ev == NULL, status == %d", status );
return G_SOURCE_CONTINUE;
}
}
uint8_t type = ev->response_type & ~0x80;
if ( type == xkb.first_event ) {
switch ( ev->pad0 )
{
case XCB_XKB_MAP_NOTIFY:
{
struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device ( nk_bindings_get_context ( xkb.bindings ), xcb->connection, xkb.device_id, 0 );
struct xkb_state *state = xkb_x11_state_new_from_device ( keymap, xcb->connection, xkb.device_id );
nk_bindings_update_keymap ( xkb.bindings, keymap, state );
xkb_keymap_unref ( keymap );
xkb_state_unref ( state );
break;
}
case XCB_XKB_STATE_NOTIFY:
{
xcb_xkb_state_notify_event_t *ksne = (xcb_xkb_state_notify_event_t *) ev;
nk_bindings_update_mask ( xkb.bindings,
ksne->baseMods,
ksne->latchedMods,
ksne->lockedMods,
ksne->baseGroup,
ksne->latchedGroup,
ksne->lockedGroup );
xcb_generic_event_t dev;
dev.response_type = 0;
main_loop_x11_event_handler_view ( &dev );
break;
}
}
return G_SOURCE_CONTINUE;
}
if ( xcb->sndisplay != NULL ) {
sn_xcb_display_process_event ( xcb->sndisplay, ev );
}
main_loop_x11_event_handler_view ( ev );
return G_SOURCE_CONTINUE;
g_main_loop_quit ( main_loop );
}
static gboolean main_loop_signal_handler_int ( G_GNUC_UNUSED gpointer data )
@ -706,55 +603,6 @@ static gboolean main_loop_signal_handler_int ( G_GNUC_UNUSED gpointer data )
return G_SOURCE_CONTINUE;
}
/** X server error depth. to handle nested errors. */
static int error_trap_depth = 0;
static void error_trap_push ( G_GNUC_UNUSED SnDisplay *display, G_GNUC_UNUSED xcb_connection_t *xdisplay )
{
++error_trap_depth;
}
static void error_trap_pop ( G_GNUC_UNUSED SnDisplay *display, xcb_connection_t *xdisplay )
{
if ( error_trap_depth == 0 ) {
g_warning ( "Error trap underflow!" );
exit ( EXIT_FAILURE );
}
xcb_flush ( xdisplay );
--error_trap_depth;
}
/** Retry count of grabbing keyboard. */
unsigned int lazy_grab_retry_count_kb = 0;
/** Retry count of grabbing pointer. */
unsigned int lazy_grab_retry_count_pt = 0;
static gboolean lazy_grab_pointer ( G_GNUC_UNUSED gpointer data )
{
// After 5 sec.
if ( lazy_grab_retry_count_pt > ( 5 * 1000 ) ) {
g_warning ( "Failed to grab pointer after %u times. Giving up.", lazy_grab_retry_count_pt );
return G_SOURCE_REMOVE;
}
if ( take_pointer ( xcb_stuff_get_root_window ( xcb ), 0 ) ) {
return G_SOURCE_REMOVE;
}
lazy_grab_retry_count_pt++;
return G_SOURCE_CONTINUE;
}
static gboolean lazy_grab_keyboard ( G_GNUC_UNUSED gpointer data )
{
// After 5 sec.
if ( lazy_grab_retry_count_kb > ( 5 * 1000 ) ) {
g_warning ( "Failed to grab keyboard after %u times. Giving up.", lazy_grab_retry_count_kb );
g_main_loop_quit ( main_loop );
return G_SOURCE_REMOVE;
}
if ( take_keyboard ( xcb_stuff_get_root_window ( xcb ), 0 ) ) {
return G_SOURCE_REMOVE;
}
lazy_grab_retry_count_kb++;
return G_SOURCE_CONTINUE;
}
static gboolean startup ( G_GNUC_UNUSED gpointer data )
{
TICK_N ( "Startup" );
@ -766,41 +614,10 @@ static gboolean startup ( G_GNUC_UNUSED gpointer data )
if ( find_arg ( "-normal-window" ) >= 0 ) {
window_flags |= MENU_NORMAL_WINDOW;
}
/**
* Create window (without showing)
*/
// Try to grab the keyboard as early as possible.
// We grab this using the rootwindow (as dmenu does it).
// this seems to result in the smallest delay for most people.
if ( ( window_flags & MENU_NORMAL_WINDOW ) == 0 ) {
if ( find_arg ( "-no-lazy-grab" ) >= 0 ) {
if ( !take_keyboard ( xcb_stuff_get_root_window ( xcb ), 500 ) ) {
g_warning ( "Failed to grab keyboard, even after %d uS.", 500 * 1000 );
g_main_loop_quit ( main_loop );
return G_SOURCE_REMOVE;
}
if ( !take_pointer ( xcb_stuff_get_root_window ( xcb ), 100 ) ) {
g_warning ( "Failed to grab mouse pointer, even after %d uS.", 100 * 1000 );
}
}
else {
if ( !take_keyboard ( xcb_stuff_get_root_window ( xcb ), 0 ) ) {
g_timeout_add ( 1, lazy_grab_keyboard, NULL );
}
if ( !take_pointer ( xcb_stuff_get_root_window ( xcb ), 0 ) ) {
g_timeout_add ( 1, lazy_grab_pointer, NULL );
}
}
}
TICK_N ( "Grab keyboard" );
__create_window ( window_flags );
TICK_N ( "Create Window" );
// Parse the keybindings.
if ( !parse_keys_abe ( xkb.bindings ) ) {
// Error dialog
return G_SOURCE_REMOVE;
}
TICK_N ( "Parse ABE" );
// Sanity check
config_sanity_check ( );
@ -960,143 +777,21 @@ int main ( int argc, char *argv[] )
return EXIT_FAILURE;
}
// Get DISPLAY, first env, then argument.
// We never modify display_str content.
char *display_str = ( char *) g_getenv ( "DISPLAY" );
find_arg_str ( "-display", &display_str );
xcb->connection = xcb_connect ( display_str, &xcb->screen_nbr );
if ( xcb_connection_has_error ( xcb->connection ) ) {
g_warning ( "Failed to open display: %s", display_str );
cleanup ();
return EXIT_FAILURE;
}
TICK_N ( "Open Display" );
rofi_collect_modi ();
rofi_collect_modi_setup ();
TICK_N ( "Collect MODI" );
xcb->screen = xcb_aux_get_screen ( xcb->connection, xcb->screen_nbr );
x11_build_monitor_layout ();
xcb_intern_atom_cookie_t *ac = xcb_ewmh_init_atoms ( xcb->connection, &xcb->ewmh );
xcb_generic_error_t *errors = NULL;
xcb_ewmh_init_atoms_replies ( &xcb->ewmh, ac, &errors );
if ( errors ) {
g_warning ( "Failed to create EWMH atoms" );
free ( errors );
}
// Discover the current active window manager.
x11_helper_discover_window_manager ();
TICK_N ( "Setup XCB" );
if ( xkb_x11_setup_xkb_extension ( xcb->connection, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION,
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, &xkb.first_event, NULL ) < 0 ) {
g_warning ( "cannot setup XKB extension!" );
cleanup ();
return EXIT_FAILURE;
}
struct xkb_context *xkb_context = xkb_context_new ( XKB_CONTEXT_NO_FLAGS );
if ( xkb_context == NULL ) {
g_warning ( "cannot create XKB context!" );
cleanup ();
return EXIT_FAILURE;
}
xkb.xcb_connection = xcb->connection;
xkb.device_id = xkb_x11_get_core_keyboard_device_id ( xcb->connection );
enum
{
required_events =
( XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
XCB_XKB_EVENT_TYPE_STATE_NOTIFY ),
required_nkn_details =
( XCB_XKB_NKN_DETAIL_KEYCODES ),
required_map_parts =
( XCB_XKB_MAP_PART_KEY_TYPES |
XCB_XKB_MAP_PART_KEY_SYMS |
XCB_XKB_MAP_PART_MODIFIER_MAP |
XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
XCB_XKB_MAP_PART_KEY_ACTIONS |
XCB_XKB_MAP_PART_VIRTUAL_MODS |
XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP ),
required_state_details =
( XCB_XKB_STATE_PART_MODIFIER_BASE |
XCB_XKB_STATE_PART_MODIFIER_LATCH |
XCB_XKB_STATE_PART_MODIFIER_LOCK |
XCB_XKB_STATE_PART_GROUP_BASE |
XCB_XKB_STATE_PART_GROUP_LATCH |
XCB_XKB_STATE_PART_GROUP_LOCK ),
};
static const xcb_xkb_select_events_details_t details = {
.affectNewKeyboard = required_nkn_details,
.newKeyboardDetails = required_nkn_details,
.affectState = required_state_details,
.stateDetails = required_state_details,
};
xcb_xkb_select_events ( xcb->connection, xkb.device_id, required_events, /* affectWhich */
0, /* clear */
required_events, /* selectAll */
required_map_parts, /* affectMap */
required_map_parts, /* map */
&details );
struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device ( xkb_context, xcb->connection, xkb.device_id, XKB_KEYMAP_COMPILE_NO_FLAGS );
if ( keymap == NULL ) {
g_warning ( "Failed to get Keymap for current keyboard device." );
cleanup ();
return EXIT_FAILURE;
}
struct xkb_state *state = xkb_x11_state_new_from_device ( keymap, xcb->connection, xkb.device_id );
if ( state == NULL ) {
g_warning ( "Failed to get state object for current keyboard device." );
cleanup ();
return EXIT_FAILURE;
}
xkb.bindings = nk_bindings_new ( xkb_context, keymap, state );
if ( xcb_connection_has_error ( xcb->connection ) ) {
g_warning ( "Connection has error" );
cleanup ();
return EXIT_FAILURE;
}
x11_setup ();
TICK_N ( "Setup xkb" );
if ( xcb_connection_has_error ( xcb->connection ) ) {
g_warning ( "Connection has error" );
cleanup ();
return EXIT_FAILURE;
}
main_loop = g_main_loop_new ( NULL, FALSE );
TICK_N ( "Setup mainloop" );
// startup not.
xcb->sndisplay = sn_xcb_display_new ( xcb->connection, error_trap_push, error_trap_pop );
if ( xcb_connection_has_error ( xcb->connection ) ) {
g_warning ( "Connection has error" );
cleanup ();
return EXIT_FAILURE;
}
if ( xcb->sndisplay != NULL ) {
xcb->sncontext = sn_launchee_context_new_from_environment ( xcb->sndisplay, xcb->screen_nbr );
}
if ( xcb_connection_has_error ( xcb->connection ) ) {
if ( !x11_setup ( main_loop ) ) {
g_warning ( "Connection has error" );
cleanup ();
return EXIT_FAILURE;
}
TICK_N ( "Startup Notification" );
TICK_N ( "Setup Display" );
// Setup keybinding
setup_abe ();
TICK_N ( "Setup abe" );
@ -1184,23 +879,30 @@ int main ( int argc, char *argv[] )
if ( find_arg_uint ( "-record-screenshots", &interval ) ) {
g_timeout_add ( 1000 / (double) interval, record, NULL );
}
main_loop_source = g_water_xcb_source_new_for_connection ( NULL, xcb->connection, main_loop_x11_event_handler, NULL, NULL );
TICK_N ( "X11 Setup " );
rofi_view_workers_initialize ();
// Create pid file
int pfd = create_pid_file ( pidfile );
if ( pfd < 0 ) {
cleanup ();
return EXIT_FAILURE;
}
textbox_setup ();
if ( !x11_late_setup () ) {
g_warning ( "Failed to properly finish display setup" );
cleanup ();
return EXIT_FAILURE;
}
TICK_N ( "Setup late Display" );
// Setup signal handling sources.
// SIGINT
g_unix_signal_add ( SIGINT, main_loop_signal_handler_int, NULL );
g_idle_add ( startup, NULL );
// Pidfile + visuals
int pfd = setup ();
if ( pfd < 0 ) {
return EXIT_FAILURE;
}
// Start mainloop.
g_main_loop_run ( main_loop );
teardown ( pfd );

View File

@ -55,10 +55,8 @@
#include "rofi.h"
#include "mode.h"
#include "xcb-internal.h"
#include "xkb-internal.h"
#include "helper.h"
#include "helper-theme.h"
#include "x11-helper.h"
#include "xrmoptions.h"
#include "dialogs/dialogs.h"
@ -653,7 +651,7 @@ void __create_window ( MenuFlags menu_flags )
};
xcb_window_t box_window = xcb_generate_id ( xcb->connection );
xcb_void_cookie_t cc = xcb_create_window_checked ( xcb->connection, depth->depth, box_window, xcb_stuff_get_root_window ( xcb ),
xcb_void_cookie_t cc = xcb_create_window_checked ( xcb->connection, depth->depth, box_window, xcb_stuff_get_root_window ( ),
0, 0, 200, 100, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
visual->visual_id, selmask, selval );
xcb_generic_error_t *error;
@ -906,7 +904,7 @@ static void update_callback ( textbox *t, unsigned int index, void *udata, TextB
else{
list = pango_attr_list_new ();
}
int icon_height = textbox_get_font_height ( t );
int icon_height = textbox_get_font_height ( t );
cairo_surface_t *icon = mode_get_icon ( state->sw, state->line_map[index], icon_height );
textbox_icon ( t, icon );
@ -974,40 +972,6 @@ void rofi_view_update ( RofiViewState *state, gboolean qr )
}
}
/**
* @param state Internal state of the menu.
* @param xse X selection event.
*
* Handle paste event.
*/
static void rofi_view_paste ( RofiViewState *state, xcb_selection_notify_event_t *xse )
{
if ( xse->property == XCB_ATOM_NONE ) {
g_warning ( "Failed to convert selection" );
}
else if ( xse->property == xcb->ewmh.UTF8_STRING ) {
gchar *text = window_get_text_prop ( CacheState.main_window, xcb->ewmh.UTF8_STRING );
if ( text != NULL && text[0] != '\0' ) {
unsigned int dl = strlen ( text );
// Strip new line
for ( unsigned int i = 0; i < dl; i++ ) {
if ( text[i] == '\n' ) {
dl = i;
}
}
// Insert string move cursor.
textbox_insert ( state->text, state->text->cursor, text, dl );
textbox_cursor ( state->text, state->text->cursor + g_utf8_strlen ( text, -1 ) );
// Force a redraw and refiltering of the text.
state->refilter = TRUE;
}
g_free ( text );
}
else {
g_warning ( "Failed" );
}
}
static void _rofi_view_reload_row ( RofiViewState *state )
{
g_free ( state->line_map );
@ -1384,122 +1348,83 @@ gboolean rofi_view_trigger_action ( RofiViewState *state, BindingsScope scope, g
return FALSE;
}
void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, xkb_stuff *xkb )
void rofi_view_handle_text ( RofiViewState *state, char *text )
{
switch ( event->response_type & ~0x80 )
{
case XCB_CONFIGURE_NOTIFY:
{
xcb_configure_notify_event_t *xce = (xcb_configure_notify_event_t *) event;
if ( xce->window == CacheState.main_window ) {
if ( state->x != xce->x || state->y != xce->y ) {
state->x = xce->x;
state->y = xce->y;
widget_queue_redraw ( WIDGET ( state->main_window ) );
}
if ( state->width != xce->width || state->height != xce->height ) {
state->width = xce->width;
state->height = xce->height;
if ( textbox_append_text ( state->text, text, strlen ( text ) ) ) {
state->refilter = TRUE;
}
}
cairo_destroy ( CacheState.edit_draw );
cairo_surface_destroy ( CacheState.edit_surf );
void rofi_view_handle_mouse_motion( RofiViewState *state, gint x, gint y )
{
state->mouse.x = x;
state->mouse.y = y;
if ( state->mouse.motion_target != NULL ) {
widget_xy_to_relative ( state->mouse.motion_target, &x, &y );
widget_motion_notify ( state->mouse.motion_target, x, y );
}
}
xcb_free_pixmap ( xcb->connection, CacheState.edit_pixmap );
CacheState.edit_pixmap = xcb_generate_id ( xcb->connection );
xcb_create_pixmap ( xcb->connection, depth->depth, CacheState.edit_pixmap, CacheState.main_window,
state->width, state->height );
void rofi_view_maybe_update ( RofiViewState *state )
{
if ( rofi_view_get_completed ( state ) ) {
// This menu is done.
rofi_view_finalize ( state );
// cleanup
if ( rofi_view_get_active () == NULL ) {
rofi_quit_main_loop();
return;
}
}
CacheState.edit_surf = cairo_xcb_surface_create ( xcb->connection, CacheState.edit_pixmap, visual, state->width, state->height );
CacheState.edit_draw = cairo_create ( CacheState.edit_surf );
g_debug ( "Re-size window based external request: %d %d", state->width, state->height );
widget_resize ( WIDGET ( state->main_window ), state->width, state->height );
}
}
break;
}
case XCB_MOTION_NOTIFY:
{
if ( config.click_to_exit == TRUE ) {
state->mouse_seen = TRUE;
}
xcb_motion_notify_event_t xme = *( (xcb_motion_notify_event_t *) event );
state->mouse.x = xme.event_x;
state->mouse.y = xme.event_y;
if ( state->mouse.motion_target != NULL ) {
gint x = state->mouse.x;
gint y = state->mouse.y;
widget_xy_to_relative ( state->mouse.motion_target, &x, &y );
widget_motion_notify ( state->mouse.motion_target, x, y );
}
break;
}
case XCB_BUTTON_PRESS:
{
xcb_button_press_event_t *bpe = (xcb_button_press_event_t *) event;
state->mouse.x = bpe->event_x;
state->mouse.y = bpe->event_y;
nk_bindings_handle_button ( xkb->bindings, bpe->detail, NK_BINDINGS_BUTTON_STATE_PRESS, bpe->time );
break;
}
case XCB_BUTTON_RELEASE:
{
xcb_button_release_event_t *bre = (xcb_button_release_event_t *) event;
nk_bindings_handle_button ( xkb->bindings, bre->detail, NK_BINDINGS_BUTTON_STATE_RELEASE, bre->time );
if ( config.click_to_exit == TRUE ) {
if ( ( CacheState.flags & MENU_NORMAL_WINDOW ) == 0 ) {
if ( ( state->mouse_seen == FALSE ) && ( bre->event != CacheState.main_window ) ) {
state->quit = TRUE;
state->retv = MENU_CANCEL;
}
}
state->mouse_seen = FALSE;
}
break;
}
// Paste event.
case XCB_SELECTION_NOTIFY:
rofi_view_paste ( state, (xcb_selection_notify_event_t *) event );
break;
case XCB_KEYMAP_NOTIFY:
{
xcb_keymap_notify_event_t *kne = (xcb_keymap_notify_event_t *) event;
for ( gint32 by = 0; by < 31; ++by ) {
for ( gint8 bi = 0; bi < 7; ++bi ) {
if ( kne->keys[by] & ( 1 << bi ) ) {
// X11 keycodes starts at 8
nk_bindings_handle_key ( xkb->bindings, ( 8 * by + bi ) + 8, NK_BINDINGS_KEY_STATE_PRESSED );
}
}
}
break;
}
case XCB_KEY_PRESS:
{
xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *) event;
gchar *text;
text = nk_bindings_handle_key ( xkb->bindings, xkpe->detail, NK_BINDINGS_KEY_STATE_PRESS );
if ( ( text != NULL ) && ( textbox_append_char ( state->text, text, strlen ( text ) ) ) ) {
state->refilter = TRUE;
}
break;
}
case XCB_KEY_RELEASE:
{
xcb_key_release_event_t *xkre = (xcb_key_release_event_t *) event;
nk_bindings_handle_key ( xkb->bindings, xkre->detail, NK_BINDINGS_KEY_STATE_RELEASE );
break;
}
default:
break;
}
// Update if requested.
if ( state->refilter ) {
rofi_view_refilter ( state );
}
rofi_view_update ( state, TRUE );
}
if ( ( event->response_type & ~0x80 ) == XCB_EXPOSE && CacheState.repaint_source == 0 ) {
void rofi_view_temp_configure_notify ( RofiViewState *state, xcb_configure_notify_event_t *xce )
{
if ( xce->window == CacheState.main_window ) {
if ( state->x != xce->x || state->y != xce->y ) {
state->x = xce->x;
state->y = xce->y;
widget_queue_redraw ( WIDGET ( state->main_window ) );
}
if ( state->width != xce->width || state->height != xce->height ) {
state->width = xce->width;
state->height = xce->height;
cairo_destroy ( CacheState.edit_draw );
cairo_surface_destroy ( CacheState.edit_surf );
xcb_free_pixmap ( xcb->connection, CacheState.edit_pixmap );
CacheState.edit_pixmap = xcb_generate_id ( xcb->connection );
xcb_create_pixmap ( xcb->connection, depth->depth, CacheState.edit_pixmap, CacheState.main_window,
state->width, state->height );
CacheState.edit_surf = cairo_xcb_surface_create ( xcb->connection, CacheState.edit_pixmap, visual, state->width, state->height );
CacheState.edit_draw = cairo_create ( CacheState.edit_surf );
g_debug ( "Re-size window based external request: %d %d", state->width, state->height );
widget_resize ( WIDGET ( state->main_window ), state->width, state->height );
}
}
}
void rofi_view_temp_click_to_exit ( RofiViewState *state, xcb_window_t target )
{
if ( ( CacheState.flags & MENU_NORMAL_WINDOW ) == 0 ) {
if ( target != CacheState.main_window ) {
state->quit = TRUE;
state->retv = MENU_CANCEL;
}
}
}
void rofi_view_frame_callback ( void )
{
if ( CacheState.repaint_source == 0 ) {
CacheState.repaint_source = g_idle_add_full ( G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL );
}
}
@ -1797,9 +1722,7 @@ void rofi_view_hide ( void )
{
if ( CacheState.main_window != XCB_WINDOW_NONE ) {
xcb_unmap_window ( xcb->connection, CacheState.main_window );
release_keyboard ( );
release_pointer ( );
xcb_flush ( xcb->connection );
x11_early_cleanup ();
}
}
@ -1895,9 +1818,12 @@ void rofi_view_set_overlay ( RofiViewState *state, const char *text )
// Within padding of window.
x_offset -= widget_padding_get_right ( WIDGET ( state->main_window ) );
// Within the border of widget.
//x_offset -= widget_padding_get_right ( WIDGET ( state->main_box ) );
//x_offset -= widget_padding_get_right ( WIDGET ( state->input_bar ) );
x_offset -= widget_get_width ( WIDGET ( state->case_indicator ) );
x_offset -= widget_get_width ( WIDGET ( state->overlay ) );
int top_offset = widget_padding_get_top ( WIDGET ( state->main_window ) );
//top_offset += widget_padding_get_top ( WIDGET ( state->main_box ) );
widget_move ( WIDGET ( state->overlay ), x_offset, top_offset );
// We want to queue a repaint.
rofi_view_queue_redraw ( );

View File

@ -367,7 +367,7 @@ static void listview_recompute_elements ( listview *lv )
char *name = g_strjoin ( ".", lv->listview_name, "element", NULL );
for ( unsigned int i = lv->cur_elements; i < newne; i++ ) {
TextboxFlags flags = ( lv->multi_select ) ? TB_INDICATOR : 0;
flags |= ((config.show_icons)? TB_ICON:0);
flags |= ( ( config.show_icons ) ? TB_ICON : 0 );
lv->boxes[i] = textbox_create_full ( WIDGET_TYPE_LISTVIEW_ELEMENT, name, flags, NORMAL, "" );
widget_set_trigger_action_handler ( WIDGET ( lv->boxes[i] ), listview_element_trigger_action, lv );
}

View File

@ -31,7 +31,6 @@
#include "widgets/textbox.h"
#include "widgets/listview.h"
#include "widgets/scrollbar.h"
#include "x11-helper.h"
#include "theme.h"

View File

@ -36,7 +36,6 @@
#include "keyb.h"
#include "helper.h"
#include "helper-theme.h"
#include "x11-helper.h"
#include "mode.h"
#include "view.h"
@ -144,8 +143,8 @@ textbox* textbox_create_full ( WidgetType type, const char *name, TextboxFlags f
tb->changed = FALSE;
tb->layout = pango_layout_new ( p_context );
if ( (tb->flags&TB_ICON) == TB_ICON) {
tb->left_offset = 1.2*textbox_get_estimated_char_height();
if ( ( tb->flags & TB_ICON ) == TB_ICON ) {
tb->left_offset = 1.2 * textbox_get_estimated_char_height ();
}
textbox_font ( tb, tbft );
@ -773,7 +772,7 @@ int textbox_keybinding ( textbox *tb, KeyBindingAction action )
}
}
gboolean textbox_append_char ( textbox *tb, const char *pad, const int pad_len )
gboolean textbox_append_text ( textbox *tb, const char *pad, const int pad_len )
{
if ( tb == NULL ) {
return FALSE;
@ -783,12 +782,18 @@ gboolean textbox_append_char ( textbox *tb, const char *pad, const int pad_len )
}
// Filter When alt/ctrl is pressed do not accept the character.
if ( !g_unichar_iscntrl ( g_utf8_get_char ( pad ) ) ) {
textbox_insert ( tb, tb->cursor, pad, pad_len );
gboolean used_something = FALSE;
const gchar *w, *n, *e;
for ( w = pad, n = g_utf8_next_char(w), e = w + pad_len ; w < e ; w = n, n = g_utf8_next_char(n) ) {
if ( g_unichar_iscntrl ( g_utf8_get_char ( w ) ) ) {
continue;
}
textbox_insert ( tb, tb->cursor, w, n - w );
textbox_cursor ( tb, tb->cursor + 1 );
return TRUE;
used_something = TRUE;
}
return FALSE;
return used_something;
}
static void tbfc_entry_free ( TBFontConfig *tbfc )

View File

@ -38,6 +38,7 @@
#include <glib.h>
#include <cairo.h>
#include <cairo-xcb.h>
#include <librsvg/rsvg.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
@ -45,17 +46,18 @@
#include <xcb/xinerama.h>
#include <xcb/xcb_ewmh.h>
#include <xcb/xproto.h>
#include <xcb/xkb.h>
#include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-x11.h>
#include "xcb-internal.h"
#include "xcb.h"
#include "settings.h"
#include "helper.h"
#include "x11-helper.h"
#include "timings.h"
#include <rofi.h>
/** Checks if the if x and y is inside rectangle. */
#define INTERSECT( x, y, x1, y1, w1, h1 ) ( ( ( ( x ) >= ( x1 ) ) && ( ( x ) < ( x1 + w1 ) ) ) && ( ( ( y ) >= ( y1 ) ) && ( ( y ) < ( y1 + h1 ) ) ) )
#include "x11-helper.h"
#include "xkb-internal.h"
WindowManager current_window_manager = WM_EWHM;
/**
@ -91,7 +93,7 @@ const char *netatom_names[] = { EWMH_ATOMS ( ATOM_CHAR ) };
cairo_surface_t *x11_helper_get_screenshot_surface ( void )
{
return cairo_xcb_surface_create ( xcb->connection,
xcb_stuff_get_root_window ( xcb ), root_visual,
xcb_stuff_get_root_window (), root_visual,
xcb->screen->width_in_pixels, xcb->screen->height_in_pixels );
}
@ -133,30 +135,6 @@ cairo_surface_t * x11_helper_get_bg_surface ( void )
xcb->screen->width_in_pixels, xcb->screen->height_in_pixels );
}
cairo_surface_t* cairo_image_surface_create_from_svg ( const gchar* file, int height )
{
cairo_surface_t *surface;
cairo_t *cr;
RsvgHandle * handle;
RsvgDimensionData dimensions;
handle = rsvg_handle_new_from_file ( file, NULL );
rsvg_handle_get_dimensions ( handle, &dimensions );
double scale = (double) height / dimensions.height;
surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32,
(double) dimensions.width * scale,
(double) dimensions.height * scale );
cr = cairo_create ( surface );
cairo_scale ( cr, scale, scale );
rsvg_handle_render_cairo ( handle, cr );
cairo_destroy ( cr );
rsvg_handle_close ( handle, NULL );
g_object_unref ( handle );
return surface;
}
// retrieve a text property from a window
// technically we could use window_get_prop(), but this is better for character set support
char* window_get_text_prop ( xcb_window_t w, xcb_atom_t atom )
@ -554,7 +532,177 @@ int monitor_active ( workarea *mon )
monitor_dimensions ( 0, 0, mon );
return FALSE;
}
int take_pointer ( xcb_window_t w, int iters )
/**
* @param state Internal state of the menu.
* @param xse X selection event.
*
* Handle paste event.
*/
static void rofi_view_paste ( RofiViewState *state, xcb_selection_notify_event_t *xse )
{
if ( xse->property == XCB_ATOM_NONE ) {
g_warning ( "Failed to convert selection" );
}
else if ( xse->property == xcb->ewmh.UTF8_STRING ) {
gchar *text = window_get_text_prop ( xse->requestor, xcb->ewmh.UTF8_STRING );
if ( text != NULL && text[0] != '\0' ) {
unsigned int dl = strlen ( text );
// Strip new line
for ( unsigned int i = 0; i < dl; i++ ) {
if ( text[i] == '\n' ) {
text[i] = '\0';
}
}
rofi_view_handle_text ( state, text );
}
g_free ( text );
}
else {
g_warning ( "Failed" );
}
}
/**
* Process X11 events in the main-loop (gui-thread) of the application.
*/
static void main_loop_x11_event_handler_view ( xcb_generic_event_t *event )
{
RofiViewState *state = rofi_view_get_active ();
if ( state == NULL ) {
return;
}
switch ( event->response_type & ~0x80 )
{
case XCB_EXPOSE:
rofi_view_frame_callback ();
break;
case XCB_CONFIGURE_NOTIFY:
{
xcb_configure_notify_event_t *xce = (xcb_configure_notify_event_t *) event;
rofi_view_temp_configure_notify ( state, xce );
break;
}
case XCB_MOTION_NOTIFY:
{
if ( config.click_to_exit == TRUE ) {
xcb->mouse_seen = TRUE;
}
xcb_motion_notify_event_t *xme = (xcb_motion_notify_event_t *) event;
rofi_view_handle_mouse_motion ( state, xme->event_x, xme->event_y );
break;
}
case XCB_BUTTON_PRESS:
{
xcb_button_press_event_t *bpe = (xcb_button_press_event_t *) event;
rofi_view_handle_mouse_motion ( state, bpe->event_x, bpe->event_y );
nk_bindings_seat_handle_button ( xcb->bindings_seat, bpe->detail, NK_BINDINGS_BUTTON_STATE_PRESS, bpe->time );
break;
}
case XCB_BUTTON_RELEASE:
{
xcb_button_release_event_t *bre = (xcb_button_release_event_t *) event;
nk_bindings_seat_handle_button ( xcb->bindings_seat, bre->detail, NK_BINDINGS_BUTTON_STATE_RELEASE, bre->time );
if ( config.click_to_exit == TRUE ) {
if ( ! xcb->mouse_seen ) {
rofi_view_temp_click_to_exit ( state, bre->event );
}
xcb->mouse_seen = FALSE;
}
break;
}
// Paste event.
case XCB_SELECTION_NOTIFY:
rofi_view_paste ( state, (xcb_selection_notify_event_t *) event );
break;
case XCB_KEYMAP_NOTIFY:
{
xcb_keymap_notify_event_t *kne = (xcb_keymap_notify_event_t *) event;
for ( gint32 by = 0; by < 31; ++by ) {
for ( gint8 bi = 0; bi < 7; ++bi ) {
if ( kne->keys[by] & ( 1 << bi ) ) {
// X11 keycodes starts at 8
nk_bindings_seat_handle_key ( xcb->bindings_seat, ( 8 * by + bi ) + 8, NK_BINDINGS_KEY_STATE_PRESSED );
}
}
}
break;
}
case XCB_KEY_PRESS:
{
xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *) event;
gchar *text;
text = nk_bindings_seat_handle_key ( xcb->bindings_seat, xkpe->detail, NK_BINDINGS_KEY_STATE_PRESS );
if ( text != NULL ) {
rofi_view_handle_text ( state, text );
}
break;
}
case XCB_KEY_RELEASE:
{
xcb_key_release_event_t *xkre = (xcb_key_release_event_t *) event;
nk_bindings_seat_handle_key ( xcb->bindings_seat, xkre->detail, NK_BINDINGS_KEY_STATE_RELEASE );
break;
}
default:
break;
}
rofi_view_maybe_update ( state );
}
static gboolean main_loop_x11_event_handler ( xcb_generic_event_t *ev, G_GNUC_UNUSED gpointer user_data )
{
if ( ev == NULL ) {
int status = xcb_connection_has_error ( xcb->connection );
if ( status > 0 ) {
g_warning ( "The XCB connection to X server had a fatal error: %d", status );
g_main_loop_quit ( xcb->main_loop );
return G_SOURCE_REMOVE;
}
else {
g_warning ( "main_loop_x11_event_handler: ev == NULL, status == %d", status );
return G_SOURCE_CONTINUE;
}
}
uint8_t type = ev->response_type & ~0x80;
if ( type == xcb->xkb.first_event ) {
switch ( ev->pad0 )
{
case XCB_XKB_MAP_NOTIFY:
{
struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device ( nk_bindings_seat_get_context ( xcb->bindings_seat ), xcb->connection, xcb->xkb.device_id, 0 );
struct xkb_state *state = xkb_x11_state_new_from_device ( keymap, xcb->connection, xcb->xkb.device_id );
nk_bindings_seat_update_keymap ( xcb->bindings_seat, keymap, state );
xkb_keymap_unref ( keymap );
xkb_state_unref ( state );
break;
}
case XCB_XKB_STATE_NOTIFY:
{
xcb_xkb_state_notify_event_t *ksne = (xcb_xkb_state_notify_event_t *) ev;
nk_bindings_seat_update_mask ( xcb->bindings_seat,
ksne->baseMods,
ksne->latchedMods,
ksne->lockedMods,
ksne->baseGroup,
ksne->latchedGroup,
ksne->lockedGroup );
rofi_view_maybe_update ( rofi_view_get_active () );
break;
}
}
return G_SOURCE_CONTINUE;
}
if ( xcb->sndisplay != NULL ) {
sn_xcb_display_process_event ( xcb->sndisplay, ev );
}
main_loop_x11_event_handler_view ( ev );
return G_SOURCE_CONTINUE;
}
static int take_pointer ( xcb_window_t w, int iters )
{
int i = 0;
while ( TRUE ) {
@ -579,7 +727,8 @@ int take_pointer ( xcb_window_t w, int iters )
}
return 0;
}
int take_keyboard ( xcb_window_t w, int iters )
static int take_keyboard ( xcb_window_t w, int iters )
{
int i = 0;
while ( TRUE ) {
@ -606,15 +755,33 @@ int take_keyboard ( xcb_window_t w, int iters )
return 0;
}
void release_keyboard ( void )
static void release_keyboard ( void )
{
xcb_ungrab_keyboard ( xcb->connection, XCB_CURRENT_TIME );
}
void release_pointer ( void )
static void release_pointer ( void )
{
xcb_ungrab_pointer ( xcb->connection, XCB_CURRENT_TIME );
}
/** X server error depth. to handle nested errors. */
static int error_trap_depth = 0;
static void error_trap_push ( G_GNUC_UNUSED SnDisplay *display, G_GNUC_UNUSED xcb_connection_t *xdisplay )
{
++error_trap_depth;
}
static void error_trap_pop ( G_GNUC_UNUSED SnDisplay *display, xcb_connection_t *xdisplay )
{
if ( error_trap_depth == 0 ) {
g_warning ( "Error trap underflow!" );
exit ( EXIT_FAILURE );
}
xcb_flush ( xdisplay );
--error_trap_depth;
}
/**
* Fill in the list of frequently used X11 Atoms.
*/
@ -631,13 +798,134 @@ static void x11_create_frequently_used_atoms ( void )
}
}
void x11_setup ( void )
gboolean x11_setup ( GMainLoop *main_loop )
{
// Get DISPLAY, first env, then argument.
// We never modify display_str content.
char *display_str = ( char *) g_getenv ( "DISPLAY" );
find_arg_str ( "-display", &display_str );
xcb->main_loop = main_loop;
xcb->source = g_water_xcb_source_new ( g_main_loop_get_context ( xcb->main_loop ), display_str, &xcb->screen_nbr, main_loop_x11_event_handler, NULL, NULL );
if ( xcb->source == NULL ) {
g_warning ( "Failed to open display: %s", display_str );
return FALSE;
}
xcb->connection = g_water_xcb_source_get_connection ( xcb->source );
TICK_N ( "Open Display" );
xcb->screen = xcb_aux_get_screen ( xcb->connection, xcb->screen_nbr );
x11_build_monitor_layout ();
xcb_intern_atom_cookie_t *ac = xcb_ewmh_init_atoms ( xcb->connection, &xcb->ewmh );
xcb_generic_error_t *errors = NULL;
xcb_ewmh_init_atoms_replies ( &xcb->ewmh, ac, &errors );
if ( errors ) {
g_warning ( "Failed to create EWMH atoms" );
free ( errors );
}
// Discover the current active window manager.
x11_helper_discover_window_manager ();
TICK_N ( "Setup XCB" );
if ( xkb_x11_setup_xkb_extension ( xcb->connection, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION,
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, &xcb->xkb.first_event, NULL ) < 0 ) {
g_warning ( "cannot setup XKB extension!" );
return FALSE;
}
xcb->xkb.device_id = xkb_x11_get_core_keyboard_device_id ( xcb->connection );
enum
{
required_events =
( XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
XCB_XKB_EVENT_TYPE_STATE_NOTIFY ),
required_nkn_details =
( XCB_XKB_NKN_DETAIL_KEYCODES ),
required_map_parts =
( XCB_XKB_MAP_PART_KEY_TYPES |
XCB_XKB_MAP_PART_KEY_SYMS |
XCB_XKB_MAP_PART_MODIFIER_MAP |
XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
XCB_XKB_MAP_PART_KEY_ACTIONS |
XCB_XKB_MAP_PART_VIRTUAL_MODS |
XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP ),
required_state_details =
( XCB_XKB_STATE_PART_MODIFIER_BASE |
XCB_XKB_STATE_PART_MODIFIER_LATCH |
XCB_XKB_STATE_PART_MODIFIER_LOCK |
XCB_XKB_STATE_PART_GROUP_BASE |
XCB_XKB_STATE_PART_GROUP_LATCH |
XCB_XKB_STATE_PART_GROUP_LOCK ),
};
static const xcb_xkb_select_events_details_t details = {
.affectNewKeyboard = required_nkn_details,
.newKeyboardDetails = required_nkn_details,
.affectState = required_state_details,
.stateDetails = required_state_details,
};
xcb_xkb_select_events ( xcb->connection, xcb->xkb.device_id, required_events, /* affectWhich */
0, /* clear */
required_events, /* selectAll */
required_map_parts, /* affectMap */
required_map_parts, /* map */
&details );
xcb->bindings = nk_bindings_new ();
xcb->bindings_seat = nk_bindings_seat_new ( xcb->bindings, XKB_CONTEXT_NO_FLAGS );
struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device ( nk_bindings_seat_get_context ( xcb->bindings_seat ), xcb->connection, xcb->xkb.device_id, XKB_KEYMAP_COMPILE_NO_FLAGS );
if ( keymap == NULL ) {
g_warning ( "Failed to get Keymap for current keyboard device." );
return FALSE;
}
struct xkb_state *state = xkb_x11_state_new_from_device ( keymap, xcb->connection, xcb->xkb.device_id );
if ( state == NULL ) {
g_warning ( "Failed to get state object for current keyboard device." );
return FALSE;
}
nk_bindings_seat_update_keymap ( xcb->bindings_seat, keymap, state );
if ( !parse_keys_abe ( xcb->bindings ) ) {
// Error dialog
return FALSE;
}
// determine numlock mask so we can bind on keys with and without it
x11_create_frequently_used_atoms ( );
if ( xcb_connection_has_error ( xcb->connection ) ) {
g_warning ( "Connection has error" );
return FALSE;
}
// startup not.
xcb->sndisplay = sn_xcb_display_new ( xcb->connection, error_trap_push, error_trap_pop );
if ( xcb_connection_has_error ( xcb->connection ) ) {
g_warning ( "Connection has error" );
return FALSE;
}
if ( xcb->sndisplay != NULL ) {
xcb->sncontext = sn_launchee_context_new_from_environment ( xcb->sndisplay, xcb->screen_nbr );
}
if ( xcb_connection_has_error ( xcb->connection ) ) {
g_warning ( "Connection has error" );
return FALSE;
}
return TRUE;
}
void x11_create_visual_and_colormap ( void )
static void x11_create_visual_and_colormap ( void )
{
xcb_depth_t *root_depth = NULL;
xcb_depth_iterator_t depth_iter;
@ -677,32 +965,110 @@ void x11_create_visual_and_colormap ( void )
}
}
xcb_window_t xcb_stuff_get_root_window ( xcb_stuff *xcb )
/** Retry count of grabbing keyboard. */
unsigned int lazy_grab_retry_count_kb = 0;
/** Retry count of grabbing pointer. */
unsigned int lazy_grab_retry_count_pt = 0;
static gboolean lazy_grab_pointer ( G_GNUC_UNUSED gpointer data )
{
// After 5 sec.
if ( lazy_grab_retry_count_pt > ( 5 * 1000 ) ) {
g_warning ( "Failed to grab pointer after %u times. Giving up.", lazy_grab_retry_count_pt );
return G_SOURCE_REMOVE;
}
if ( take_pointer ( xcb_stuff_get_root_window (), 0 ) ) {
return G_SOURCE_REMOVE;
}
lazy_grab_retry_count_pt++;
return G_SOURCE_CONTINUE;
}
static gboolean lazy_grab_keyboard ( G_GNUC_UNUSED gpointer data )
{
// After 5 sec.
if ( lazy_grab_retry_count_kb > ( 5 * 1000 ) ) {
g_warning ( "Failed to grab keyboard after %u times. Giving up.", lazy_grab_retry_count_kb );
g_main_loop_quit ( xcb->main_loop );
return G_SOURCE_REMOVE;
}
if ( take_keyboard ( xcb_stuff_get_root_window (), 0 ) ) {
return G_SOURCE_REMOVE;
}
lazy_grab_retry_count_kb++;
return G_SOURCE_CONTINUE;
}
gboolean x11_late_setup ( void )
{
x11_create_visual_and_colormap ();
/**
* Create window (without showing)
*/
// Try to grab the keyboard as early as possible.
// We grab this using the rootwindow (as dmenu does it).
// this seems to result in the smallest delay for most people.
if ( find_arg ( "-normal-window" ) >= 0 ) {
return TRUE;
}
if ( find_arg ( "-no-lazy-grab" ) >= 0 ) {
if ( !take_keyboard ( xcb_stuff_get_root_window (), 500 ) ) {
g_warning ( "Failed to grab keyboard, even after %d uS.", 500 * 1000 );
return FALSE;
}
if ( !take_pointer ( xcb_stuff_get_root_window (), 100 ) ) {
g_warning ( "Failed to grab mouse pointer, even after %d uS.", 100 * 1000 );
}
}
else {
if ( !take_keyboard ( xcb_stuff_get_root_window (), 0 ) ) {
g_timeout_add ( 1, lazy_grab_keyboard, NULL );
}
if ( !take_pointer ( xcb_stuff_get_root_window (), 0 ) ) {
g_timeout_add ( 1, lazy_grab_pointer, NULL );
}
}
return TRUE;
}
xcb_window_t xcb_stuff_get_root_window ( void )
{
return xcb->screen->root;
}
void xcb_stuff_wipe ( xcb_stuff *xcb )
void x11_early_cleanup ( void )
{
if ( xcb->connection != NULL ) {
g_debug ( "Cleaning up XCB and XKB" );
if ( xcb->sncontext != NULL ) {
sn_launchee_context_unref ( xcb->sncontext );
xcb->sncontext = NULL;
}
if ( xcb->sndisplay != NULL ) {
sn_display_unref ( xcb->sndisplay );
xcb->sndisplay = NULL;
}
x11_monitors_free ();
xcb_ewmh_connection_wipe ( &( xcb->ewmh ) );
xcb_flush ( xcb->connection );
xcb_aux_sync ( xcb->connection );
xcb_disconnect ( xcb->connection );
xcb->connection = NULL;
xcb->screen = NULL;
xcb->screen_nbr = 0;
release_keyboard ( );
release_pointer ( );
xcb_flush ( xcb->connection );
}
void xcb_stuff_wipe ( void )
{
if ( xcb->connection == NULL ) {
return;
}
g_debug ( "Cleaning up XCB and XKB" );
nk_bindings_seat_free ( xcb->bindings_seat );
nk_bindings_free ( xcb->bindings );
if ( xcb->sncontext != NULL ) {
sn_launchee_context_unref ( xcb->sncontext );
xcb->sncontext = NULL;
}
if ( xcb->sndisplay != NULL ) {
sn_display_unref ( xcb->sndisplay );
xcb->sndisplay = NULL;
}
x11_monitors_free ();
xcb_ewmh_connection_wipe ( &( xcb->ewmh ) );
xcb_flush ( xcb->connection );
xcb_aux_sync ( xcb->connection );
g_water_xcb_source_free ( xcb->source );
xcb->source = NULL;
xcb->connection = NULL;
xcb->screen = NULL;
xcb->screen_nbr = 0;
}
void x11_disable_decoration ( xcb_window_t window )
@ -734,7 +1100,7 @@ void x11_helper_discover_window_manager ( void )
{
xcb_window_t wm_win = 0;
xcb_get_property_cookie_t cc = xcb_ewmh_get_supporting_wm_check_unchecked ( &xcb->ewmh,
xcb_stuff_get_root_window ( xcb ) );
xcb_stuff_get_root_window () );
if ( xcb_ewmh_get_supporting_wm_check_reply ( &xcb->ewmh, cc, &wm_win, NULL ) ) {
xcb_ewmh_get_utf8_strings_reply_t wtitle;

View File

@ -36,7 +36,6 @@
#include <glib.h>
#include "xcb.h"
#include "xcb-internal.h"
#include "x11-helper.h"
#include "rofi.h"
#include "xrmoptions.h"
#include "settings.h"

@ -1 +1 @@
Subproject commit a997ea9ef7c8805f928ea325b0463931284afa17
Subproject commit 53314c0ab58d1a677d61017a413fd1d83b05ce3c

View File

@ -32,12 +32,12 @@
#include <helper.h>
#include <string.h>
#include <xcb/xcb_ewmh.h>
#include "xcb.h"
#include "xcb-internal.h"
#include "rofi.h"
#include "settings.h"
static int test = 0;
struct xcb_stuff *xcb;
#define TASSERT( a ) { \
assert ( a ); \
@ -60,6 +60,11 @@ int rofi_view_error_dialog ( const char *msg, G_GNUC_UNUSED int markup )
return TRUE;
}
int monitor_active ( G_GNUC_UNUSED workarea *mon )
{
return 0;
}
int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char ** argv )
{

View File

@ -32,12 +32,12 @@
#include <helper.h>
#include <string.h>
#include <xcb/xcb_ewmh.h>
#include "xcb.h"
#include "xcb-internal.h"
#include "rofi.h"
#include "settings.h"
static int test = 0;
struct xcb_stuff *xcb;
#define TASSERT( a ) { \
assert ( a ); \
@ -61,10 +61,10 @@ int rofi_view_error_dialog ( const char *msg, G_GNUC_UNUSED int markup )
return TRUE;
}
xcb_screen_t *xcb_screen;
xcb_ewmh_connection_t xcb_ewmh;
int xcb_screen_nbr;
#include <x11-helper.h>
int monitor_active ( G_GNUC_UNUSED workarea *mon )
{
return 0;
}
int main ( int argc, char ** argv )
{

View File

@ -32,6 +32,7 @@
#include <helper.h>
#include <string.h>
#include <xcb/xcb_ewmh.h>
#include "xcb.h"
#include "xcb-internal.h"
#include "rofi.h"
#include "settings.h"
@ -50,11 +51,10 @@ int rofi_view_error_dialog ( const char *msg, G_GNUC_UNUSED int markup )
fputs ( msg, stderr );
return TRUE;
}
xcb_screen_t *xcb_screen;
xcb_ewmh_connection_t xcb_ewmh;
int xcb_screen_nbr;
#include <x11-helper.h>
int monitor_active ( G_GNUC_UNUSED workarea *mon )
{
return 0;
}
int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char ** argv )
{

View File

@ -32,12 +32,12 @@
#include <helper.h>
#include <string.h>
#include <xcb/xcb_ewmh.h>
#include "xcb.h"
#include "xcb-internal.h"
#include "rofi.h"
#include "settings.h"
static int test = 0;
struct xcb_stuff *xcb;
#define TASSERT( a ) { \
assert ( a ); \
@ -70,10 +70,10 @@ int rofi_view_error_dialog ( const char *msg, G_GNUC_UNUSED int markup )
return TRUE;
}
xcb_screen_t *xcb_screen;
xcb_ewmh_connection_t xcb_ewmh;
int xcb_screen_nbr;
#include <x11-helper.h>
int monitor_active ( G_GNUC_UNUSED workarea *mon )
{
return 0;
}
int main ( int argc, char ** argv )
{

View File

@ -32,6 +32,7 @@
#include <helper.h>
#include <string.h>
#include <xcb/xcb_ewmh.h>
#include "xcb.h"
#include "xcb-internal.h"
#include "rofi.h"
#include "settings.h"
@ -50,11 +51,10 @@ int rofi_view_error_dialog ( const char *msg, G_GNUC_UNUSED int markup )
fputs ( msg, stderr );
return TRUE;
}
xcb_screen_t *xcb_screen;
xcb_ewmh_connection_t xcb_ewmh;
int xcb_screen_nbr;
#include <x11-helper.h>
int monitor_active ( G_GNUC_UNUSED workarea *mon )
{
return 0;
}
int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char ** argv )
{

View File

@ -38,7 +38,7 @@
#include <dialogs/help-keys.h>
#include <xkbcommon/xkbcommon.h>
#include "rofi.h"
#include "x11-helper.h"
#include "xcb.h"
#include <keyb.h>
#include <helper.h>

View File

@ -37,6 +37,7 @@
#include <widgets/textbox.h>
#include <rofi.h>
#include <cairo-xlib.h>
#include "xcb.h"
#include "settings.h"
#include "xrmoptions.h"
@ -70,6 +71,11 @@ int rofi_view_error_dialog ( const char *msg, G_GNUC_UNUSED int markup )
return FALSE;
}
int monitor_active ( G_GNUC_UNUSED workarea *mon )
{
return 0;
}
int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv )
{
cairo_surface_t *surf = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, 100, 100 );

View File

@ -35,6 +35,7 @@
#include "xcb-internal.h"
#include "rofi.h"
#include "settings.h"
#include "xcb.h"
#include "theme.h"
#include "css-colors.h"
#include "widgets/widget-internal.h"
@ -63,10 +64,12 @@ double textbox_get_estimated_char_height ( void )
{
return 16.0;
}
xcb_screen_t *xcb_screen;
xcb_ewmh_connection_t xcb_ewmh;
int xcb_screen_nbr;
#include <x11-helper.h>
int monitor_active ( G_GNUC_UNUSED workarea *mon )
{
return 0;
}
#ifndef _ck_assert_ptr_null
/* Pointer against NULL comparison macros with improved output
* compared to ck_assert(). */

View File

@ -36,6 +36,7 @@
#include <widgets/widget-internal.h>
#include "rofi.h"
#include "xrmoptions.h"
#include "xcb.h"
unsigned int test =0;
#define TASSERT( a ) { \
assert ( a ); \
@ -50,6 +51,10 @@ void rofi_add_error_message ( G_GNUC_UNUSED GString *msg )
void rofi_view_queue_redraw ( void )
{
}
int monitor_active ( G_GNUC_UNUSED workarea *mon )
{
return 0;
}
void rofi_view_get_current_monitor ( G_GNUC_UNUSED int *width, G_GNUC_UNUSED int *height )
{