Switch Cursor on Movable Area in Electron

Working on a project in Electron and having some trouble with a frameless window. I have designated certain top areas as draggable using -webkit-app-region: drag, but the cursor will not change as expected.

Although this code snippet won't make the element draggable, the cursor should change when attempting to drag the designated area.

UPDATE: After further testing, it seems that changing the cursor for any webkit style is not functioning properly. This issue extends to trying to modify the cursor for a scrollbar as well. Have tried searching for solutions online, but nothing seems to address this specific problem.

#draggable {
  -webkit-app-region: drag;
  cursor: grab;
  height: 40px;
  width: 90%;
  margin: 0;
  background-color: #393939;
  color: #000;
  position: absolute;
  z-index: 2;
  top: 0;
  border-bottom: 3px solid #202020;
}
#draggable:hover {
  cursor: grab;
}
<div id="draggable">
   <h3 style="margin: 5px 0 0 10px;">Hardware Application</h3>
</div>

Answer №1

Regrettably, when setting -webkit-app-region: drag;, it disables all click and mouse events as it is perceived as a title-bar, thus preventing the cursor from being changed.

I recall reading about this issue, but unfortunately, I can no longer locate the source.

Please refer to:

#1354 -webkit-app-region: drag eats all click events

#8730 Frameless Electron App not work css cursor:pointer

Answer №2

Apologies, but there is an alternative available that comes with a few limitations:

Here's an example of a title bar in react-ts that tracks mouse movement during dragging:

function Header({ leading, navigation, following }: HeaderProps) {
  const navigate = useNavigate();
  const [, startTransition] = useTransition();
  const [dragging, setDragging] = useState(false);
  return (
    <div
      className="titleBar"
      onMouseDown={() => {
        setDragging(true);
      }}
      onMouseUp={() => {
        setDragging(false);
      }}
      onMouseLeave={() => {
        setDragging(false);
      }}
      onMouseMove={(e) => {
        if (dragging) {
          window.electron.ipcRenderer.sendMessage(
            'window',
            'move',
            e.movementX,
            e.movementY
          );
        }
      }}
    >
      <div className="flexrow_start">
        {leading}
        <div>
          {navigation.map((info, index) => (
            <button
              type="button"
              onClick={(e) => {
                e.preventDefault();
                startTransition(() => {
                  navigate(info.destination ?? '/');
                });
              }}
              key={index}
            >
              {info.content}
            </button>
          ))}
        </div>
      </div>
      {following !== undefined && (
        <div className="flexrow_end"> {following}</div>
      )}
    </div>
  );
}

In your main.ts file:

ipcMain.on('window', (e, arg, arg2, arg3) => {
  switch (arg as string) {
    // action triggered from element in header for minimizing window
    case 'min':
      mainWindow?.minimize();
      break;
    // action triggered from element in header for maximizing window
    case 'max':
      if (mainWindow?.isMaximized()) {
        mainWindow.unmaximize();
      } else {
        mainWindow?.maximize();
      }
      break;
    // action triggered from element in header for closing app
    case 'close':
      app.quit();
      break;
    // movement handler for header element dragging
    case 'move':
      console.log(arg2, arg3);
      mainWindow?.setPosition(
        mainWindow.getPosition()[0] + arg2,
        mainWindow.getPosition()[1] + arg3
      );
      break;
    default:
      break;
  }
});
.titleBar{
  height: 50px;
  display: flex;
  justify-content: space-between;
}
.titleBar:hover{
  cursor: grab;
}

NOTE: This solution may not work optimally when moving the electron app between displays. If you have a workaround for this issue, please feel free to share in the comments. Thank you!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I encountered an error stating that "paypal is not defined" while configuring PayPal Checkout with vue.js

Recently, I created a component called PaypalButton.vue. I followed the instructions provided here to implement the button: https://developer.paypal.com/docs/checkout/integrate/# <template> <div> <div id="paypal-button-container&q ...

The custom bullet points are not appearing correctly

I've been attempting to design a custom bullet list, but it doesn't look quite right as I had hoped. The issue is that the spacing appears too close, you can see an example HERE Any suggestions would be greatly appreciated. Thank you ...

Submitting an Ajax form refreshes the page

After submitting the form, the page reloads and I am trying to prevent that from happening. Latest Update: After receiving some feedback, I have made changes to my code. The form submission now works correctly, but the page still reloads. Previously, this ...

Implementing Winston logging into a React JS project

I am looking to integrate Winston logging into my React application that was created using create-react-app. First, I installed Winston by running the following command: npm install winston Next, I imported Winston into my app.js file like so: import win ...

transfer the variable from one module to another JavaScript file

I have developed a custom module and I am facing an issue where I need to pass the fetched database value $flag=1 to a JavaScript file in Drupal 7. However, when I try to access the variable 'aniv' in the JavaScript file, it shows as 'undefi ...

Tips for eliminating redundancy in JavaScript when updating an UpdatePanel in ASP.NET

If JavaScript code is not functioning after the UpdatePanel has been refreshed, it needs to be handled properly. There are multiple ways to address this issue. One preferred method involves implementing the following: <script language="javascript" type ...

Ways to selectively implement the callback of setState using hooks in specific locations, rather than applying it universally

There are times when I need to set a state and perform an action afterwards, but other times not! How can I achieve this using hooks? Sometimes, I want to call a function or do something after setting the state: this.setState({inputValue:'someValue& ...

Error message: Cannot establish the attribute 'next' on the string '/:id'

I encountered an error while trying to develop an API for a travel company. The error message "TypeError: Cannot create property 'next' on string '/:id'" keeps popping up, even though all the necessary functions are already created. con ...

Is it possible to have the logo centered with the menu bar?

I found a cool theme: Check it out here! Does anyone know how to center the logo and menubar on this template? <section class="page_toplogo ls s-pt-25 s-pb-20 s-py-md-30"> <div class="container"> ...

Vue.js encountered an uncaught TypeError while trying to execute the 'drawImage' function

I am facing an issue with my vue.js application where I can successfully apply a filter to a photo, but I am unable to post it. The error message I am encountering is: Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingCon ...

Display checkboxes on all TableRow elements as soon as one of them is checked

I've incorporated a material-ui Table into my project and have successfully implemented multi-select functionality. Here are the requirements I've fulfilled so far: Checkboxes are initially hidden - COMPLETED Hovering over a row reveals its che ...

What strategies can be employed to prevent the need for custom classes for each individual paragraph or list item in order to maintain consistent styles within a

Bootstrap typically removes default paragraph margins and list styles for a cleaner look. However, there may be cases where you want to maintain the default styles for paragraphs and lists within a section of user-generated content on a Bootstrap 5-styled ...

What is the best way to ensure that a specified number of list items (li) will align properly within the width of an unordered list (ul

I'm attempting to make all the li elements' width match that of my ul element. Here is the code I am using: http://jsfiddle.net/4XR5V/2/ I have looked at some similar questions on the website and tried adding: ul { width: 100%; display: tab ...

What could be causing the unexpected white gap within my div element even though I've adjusted its dimensions to be minimal?

<div style=" height:0; width: 0 ; border: 1px solid black ; "> This code snippet displays a div element with a specified height, width, and border color. However, there seems to be an issue with the rendering as some st ...

Set dimensions for the input submit border inside

Can anyone help me figure out how to prevent the border from being drawn inside of my submit button element? I have a specific width and height set for cross-browser consistency, but in Firefox 15 and IE7 the border gets applied to the inside of the elemen ...

Update the page by selecting the refresh option from the drop-down menu

In my script, I have different views showing information retrieved from a database. One view displays the quantity of a product sold each month, another shows sales, the third presents profits, and the last exhibits calculated percentages using sales and p ...

sending a value from HTML to jQuery

I'm attempting to send a parameter from HTML to jQuery, but I seem to be getting the same answer each time even though I'm using a for loop in my PHP file like this: for ($x = 0; $x < $length; $x++) { echo "<button ><a class=' ...

Is the size of the JSON file inhibiting successful parsing?

After retrieving a large list of schools with their respective columns from the database, totaling over 1000 rows, I converted it to JSON and passed it to my view. I then attempted to parse it using $.parseJSON('@Html.Raw(Model.subChoiceJsonString)& ...

Blend the power of Dynamic classes with data binders in Vue.js

Recently, I've been working on a v-for loop in HTML that looks like this: <ul v-for="(item, index) in openweathermap.list"> <li>{{item.dt_txt}}</li> <li>{{item.weather[0].description}}</li> <li>{{item.w ...

The remaining visible portion of a viewport is equivalent to the height of an element

Is there a way to dynamically set a div's height so that it expands from its starting position to the end of its parent div, which is 100% of the viewport minus 20 pixels? Here is an example of how you can achieve this using jQuery: $(document).read ...